Warning: Permanently added '3.239.63.59' (ED25519) to the list of known hosts. You can reproduce this build on your computer by running: sudo dnf install copr-rpmbuild /usr/bin/copr-rpmbuild --verbose --drop-resultdir --task-url https://copr.fedorainfracloud.org/backend/get-build-task/11200695-fedora-rawhide-x86_64 --chroot fedora-rawhide-x86_64 Version: 1.10 PID: 11875 Logging PID: 11877 Task: {'allow_user_ssh': False, 'appstream': False, 'background': False, 'build_id': 11200695, 'buildroot_pkgs': [], 'chroot': 'fedora-rawhide-x86_64', 'enable_net': False, 'fedora_review': False, 'git_hash': 'b8a12e4556de21de570cf253073fba29bf0b3a85', 'git_repo': 'https://copr-dist-git.fedorainfracloud.org/git/mhough/biofedora/python-sbmlutils', 'isolation': 'default', 'memory_reqs': 2048, 'package_name': 'python-sbmlutils', 'package_version': '0.17.0-1', 'project_dirname': 'biofedora', 'project_name': 'biofedora', 'project_owner': 'mhough', 'repo_priority': None, 'repos': [{'baseurl': 'https://download.copr.fedorainfracloud.org/results/mhough/biofedora/fedora-rawhide-x86_64/', 'id': 'copr_base', 'name': 'Copr repository', 'priority': None, 'repo_gpgcheck': False}, {'baseurl': 'https://download.copr.fedorainfracloud.org/results/mhough/neurofedora/fedora-rawhide-x86_64/', 'id': 'copr_mhough_neurofedora', 'name': 'Additional repo copr_mhough_neurofedora', 'repo_gpgcheck': False}], 'sandbox': 'mhough/biofedora--mhough', 'source_json': {}, 'source_type': None, 'ssh_public_keys': None, 'storage': 1, 'submitter': 'mhough', 'tags': [], 'task_id': '11200695-fedora-rawhide-x86_64', 'timeout': 18000, 'uses_devel_repo': False, 'with_opts': [], 'without_opts': []} Running: git clone https://copr-dist-git.fedorainfracloud.org/git/mhough/biofedora/python-sbmlutils /var/lib/copr-rpmbuild/workspace/workdir-0bdhkoy4/python-sbmlutils --depth 500 --no-single-branch --recursive cmd: ['git', 'clone', 'https://copr-dist-git.fedorainfracloud.org/git/mhough/biofedora/python-sbmlutils', '/var/lib/copr-rpmbuild/workspace/workdir-0bdhkoy4/python-sbmlutils', '--depth', '500', '--no-single-branch', '--recursive'] cwd: . rc: 0 stdout: stderr: Cloning into '/var/lib/copr-rpmbuild/workspace/workdir-0bdhkoy4/python-sbmlutils'... Running: git checkout b8a12e4556de21de570cf253073fba29bf0b3a85 -- cmd: ['git', 'checkout', 'b8a12e4556de21de570cf253073fba29bf0b3a85', '--'] cwd: /var/lib/copr-rpmbuild/workspace/workdir-0bdhkoy4/python-sbmlutils rc: 0 stdout: stderr: Note: switching to 'b8a12e4556de21de570cf253073fba29bf0b3a85'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -c with the switch command. Example: git switch -c Or undo this operation with: git switch - Turn off this advice by setting config variable advice.detachedHead to false HEAD is now at b8a12e4 automatic import of python-sbmlutils Running: dist-git-client sources cmd: ['dist-git-client', 'sources'] cwd: /var/lib/copr-rpmbuild/workspace/workdir-0bdhkoy4/python-sbmlutils rc: 0 stdout: stderr: INFO: Reading stdout from command: git rev-parse --abbrev-ref HEAD INFO: Reading stdout from command: git rev-parse HEAD INFO: Reading sources specification file: sources INFO: Downloading sbmlutils-0.17.0.tar.gz INFO: Reading stdout from command: curl --help all INFO: Calling: curl -H Pragma: -H 'Accept-Encoding: identity' -o sbmlutils-0.17.0.tar.gz --location --connect-timeout 60 --retry 3 --retry-delay 10 --remote-time --show-error --fail --retry-all-errors https://copr-dist-git.fedorainfracloud.org/repo/pkgs/mhough/biofedora/python-sbmlutils/sbmlutils-0.17.0.tar.gz/md5/09507bedac253cc7ee879224133ff772/sbmlutils-0.17.0.tar.gz % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 3.57M 100 3.57M 0 0 247.6M 0 0 INFO: Reading stdout from command: md5sum sbmlutils-0.17.0.tar.gz tail: /var/lib/copr-rpmbuild/main.log: file truncated Running (timeout=18000): unbuffer mock --spec /var/lib/copr-rpmbuild/workspace/workdir-0bdhkoy4/python-sbmlutils/python-sbmlutils.spec --sources /var/lib/copr-rpmbuild/workspace/workdir-0bdhkoy4/python-sbmlutils --resultdir /var/lib/copr-rpmbuild/results --uniqueext 1792824742.145479 -r /var/lib/copr-rpmbuild/results/configs/child.cfg INFO: mock.py version 6.9 starting (python version = 3.14.5, NVR = mock-6.9-1.fc44), args: /usr/libexec/mock/mock --spec /var/lib/copr-rpmbuild/workspace/workdir-0bdhkoy4/python-sbmlutils/python-sbmlutils.spec --sources /var/lib/copr-rpmbuild/workspace/workdir-0bdhkoy4/python-sbmlutils --resultdir /var/lib/copr-rpmbuild/results --uniqueext 1792824742.145479 -r /var/lib/copr-rpmbuild/results/configs/child.cfg Start(bootstrap): init plugins INFO: tmpfs initialized INFO: selinux enabled INFO: chroot_scan: initialized INFO: compress_logs: initialized Finish(bootstrap): init plugins Start: init plugins INFO: tmpfs initialized INFO: selinux enabled INFO: chroot_scan: initialized INFO: compress_logs: initialized Finish: init plugins INFO: Signal handler active Start: run INFO: Start(/var/lib/copr-rpmbuild/workspace/workdir-0bdhkoy4/python-sbmlutils/python-sbmlutils.spec) Config(fedora-rawhide-x86_64) Start: clean chroot Finish: clean chroot Mock Version: 6.9 INFO: Mock Version: 6.9 Start(bootstrap): chroot init INFO: mounting tmpfs at /var/lib/mock/fedora-rawhide-x86_64-bootstrap-1792824742.145479/root. INFO: calling preinit hooks INFO: enabled root cache INFO: enabled package manager cache Start(bootstrap): cleaning package manager metadata Finish(bootstrap): cleaning package manager metadata INFO: Guessed host environment type: unknown INFO: Using container image: registry.fedoraproject.org/fedora:rawhide INFO: Pulling image: registry.fedoraproject.org/fedora:rawhide INFO: Tagging container image as mock-bootstrap-c7014eef-0715-4d37-9207-1ddae2116fe7 INFO: Checking that 428f565534c378b103a8ec89b338164726967d88fa562966ed69cf5b3af100aa image matches host's architecture INFO: Copy content of container 428f565534c378b103a8ec89b338164726967d88fa562966ed69cf5b3af100aa to /var/lib/mock/fedora-rawhide-x86_64-bootstrap-1792824742.145479/root INFO: mounting 428f565534c378b103a8ec89b338164726967d88fa562966ed69cf5b3af100aa with podman image mount INFO: image 428f565534c378b103a8ec89b338164726967d88fa562966ed69cf5b3af100aa as /var/lib/containers/storage/overlay/f3bc5b33644f09b51b39df99e8ac68c870b366f98319c7db0cebb8708e479ff9/merged INFO: umounting image 428f565534c378b103a8ec89b338164726967d88fa562966ed69cf5b3af100aa (/var/lib/containers/storage/overlay/f3bc5b33644f09b51b39df99e8ac68c870b366f98319c7db0cebb8708e479ff9/merged) with podman image umount INFO: Removing image mock-bootstrap-c7014eef-0715-4d37-9207-1ddae2116fe7 INFO: Package manager dnf5 detected and used (fallback) INFO: Not updating bootstrap chroot, bootstrap_image_ready=True Start(bootstrap): creating root cache Finish(bootstrap): creating root cache Finish(bootstrap): chroot init Start: chroot init INFO: mounting tmpfs at /var/lib/mock/fedora-rawhide-x86_64-1792824742.145479/root. INFO: calling preinit hooks INFO: enabled root cache INFO: enabled package manager cache Start: cleaning package manager metadata Finish: cleaning package manager metadata INFO: enabled HW Info plugin INFO: Package manager dnf5 detected and used (direct choice) INFO: Buildroot is handled by package management downloaded with a bootstrap image: rpm-6.1.0-1.fc46.x86_64 rpm-sequoia-1.10.3-1.fc46.x86_64 dnf5-5.4.6.0-1.fc46.x86_64 dnf5-plugins-5.4.6.0-1.fc46.x86_64 Start: installing minimal buildroot with dnf5 Updating and loading repositories: Additional repo copr_mhough_neurofedor 100% | 2.2 MiB/s | 972.1 KiB | 00m00s fedora 100% | 35.9 MiB/s | 22.0 MiB | 00m01s Copr repository 100% | 114.1 KiB/s | 68.6 KiB | 00m01s Repositories loaded. Package Arch Version Repository Size Installing group/module packages: bash x86_64 0:5.3.20-1.fc46 fedora 8.5 MiB bzip2 x86_64 0:1.0.8-24.fc45 fedora 95.0 KiB coreutils x86_64 0:9.12-1.fc46 fedora 6.3 MiB cpio x86_64 0:2.15-10.fc45 fedora 1.1 MiB diffutils x86_64 0:3.12-6.fc45 fedora 1.6 MiB fedora-release-common noarch 0:46-0.1 fedora 4.6 KiB findutils x86_64 1:4.11.0-2.fc45 fedora 1.9 MiB gawk x86_64 0:5.4.1-1.fc45 fedora 2.2 MiB glibc-minimal-langpack x86_64 0:2.44.9000-5.fc46 fedora 0.0 B grep x86_64 0:3.12-4.fc45 fedora 1.0 MiB gzip x86_64 0:1.15-1.fc46 fedora 445.2 KiB info x86_64 0:7.3-3.fc45 fedora 372.4 KiB patch x86_64 0:2.8-6.fc46 fedora 226.6 KiB redhat-rpm-config noarch 0:345-5.fc46 fedora 184.3 KiB rpm-build x86_64 0:6.1.0-1.fc46 fedora 312.1 KiB sed x86_64 0:4.10-2.fc45 fedora 866.5 KiB shadow-utils x86_64 2:4.20.0-2.fc46 fedora 3.9 MiB tar x86_64 2:1.35-9.fc45 fedora 3.0 MiB unzip x86_64 0:6.0-71.fc45 fedora 441.8 KiB util-linux x86_64 0:2.42.4-2.fc46 fedora 3.7 MiB which x86_64 0:2.25-2.fc45 fedora 83.6 KiB xz x86_64 1:5.8.4-1.fc46 fedora 1.4 MiB Installing dependencies: R-srpm-macros noarch 0:1.3.7-3.fc45 fedora 3.5 KiB add-determinism x86_64 0:0.7.3-3.fc45 fedora 2.2 MiB alternatives x86_64 0:1.33-6.fc45 fedora 62.1 KiB ansible-srpm-macros noarch 0:1-22.fc45 fedora 35.7 KiB audit-libs x86_64 0:4.2.1-2.fc45 fedora 390.5 KiB binutils x86_64 0:2.47.50-20.fc46 fedora 24.5 MiB build-reproducibility-srpm-macros noarch 0:0.7.3-3.fc45 fedora 1.2 KiB bzip2-libs x86_64 0:1.0.8-24.fc45 fedora 80.5 KiB ca-certificates noarch 0:2026.2.92_v9.0.319-2.fc46 fedora 2.7 MiB cmake-srpm-macros noarch 0:4.3.0-5.fc45 fedora 524.0 B coreutils-common x86_64 0:9.12-1.fc46 fedora 11.5 MiB crypto-policies noarch 0:20260713-2.gitc42da77.fc45 fedora 134.3 KiB curl x86_64 0:8.23.0-1.fc46 fedora 486.1 KiB cyrus-sasl-lib x86_64 0:2.1.28-37.fc45 fedora 2.3 MiB debugedit x86_64 0:5.3-3.fc45 fedora 220.8 KiB dwz x86_64 0:0.17-3.fc45 fedora 291.1 KiB ed x86_64 0:1.22.6-1.fc46 fedora 150.9 KiB efi-srpm-macros noarch 0:6-9.fc45 fedora 40.3 KiB elfutils x86_64 0:0.197-1.fc46 fedora 3.1 MiB elfutils-debuginfod-client x86_64 0:0.197-1.fc46 fedora 79.9 KiB elfutils-libelf x86_64 0:0.197-1.fc46 fedora 1.6 MiB elfutils-libs x86_64 0:0.197-1.fc46 fedora 719.5 KiB erlang-srpm-macros noarch 0:0.4.0-1.fc46 fedora 2.0 KiB fedora-gpg-keys noarch 0:46-0.3 fedora 130.3 KiB fedora-release noarch 0:46-0.1 fedora 0.0 B fedora-release-identity-basic noarch 0:46-0.1 fedora 664.0 B fedora-repos noarch 0:46-0.3 fedora 4.9 KiB fedora-repos-rawhide noarch 0:46-0.3 fedora 2.2 KiB file x86_64 0:5.48-3.fc46 fedora 101.9 KiB file-libs x86_64 0:5.48-3.fc46 fedora 12.3 MiB filesystem x86_64 0:3.18-59.fc45 fedora 112.0 B filesystem-srpm-macros noarch 0:3.18-59.fc45 fedora 38.2 KiB fips-provider x86_64 0:1.5.3-1.fc46 fedora 4.8 MiB fonts-srpm-macros noarch 1:5.0.0-4.fc45 fedora 55.8 KiB forge-srpm-macros noarch 0:0.4.0-5.fc45 fedora 38.9 KiB fpc-srpm-macros noarch 0:1.3-17.fc45 fedora 144.0 B gap-srpm-macros noarch 0:2-3.fc45 fedora 2.1 KiB gdb-minimal x86_64 0:18.1-1.fc46 fedora 14.4 MiB gdbm-libs x86_64 1:1.26-1.fc46 fedora 134.2 KiB ghc-srpm-macros noarch 0:1.10-2.fc45 fedora 792.0 B glibc x86_64 0:2.44.9000-5.fc46 fedora 7.2 MiB glibc-common x86_64 0:2.44.9000-5.fc46 fedora 1.0 MiB glibc-gconv-extra x86_64 0:2.44.9000-5.fc46 fedora 7.7 MiB gmp x86_64 1:6.3.0-6.fc45 fedora 815.2 KiB gnat-srpm-macros noarch 0:7-3.fc45 fedora 1.0 KiB gnome-srpm-macros noarch 0:1.0-2.fc45 fedora 3.5 KiB gnulib-l10n noarch 0:20241231-4.fc45 fedora 655.0 KiB gnupg2 x86_64 0:2.4.9-18.fc45 fedora 6.5 MiB gnupg2-dirmngr x86_64 0:2.4.9-18.fc45 fedora 630.1 KiB gnupg2-gpg-agent x86_64 0:2.4.9-18.fc45 fedora 678.8 KiB gnupg2-gpgconf x86_64 0:2.4.9-18.fc45 fedora 253.8 KiB gnupg2-keyboxd x86_64 0:2.4.9-18.fc45 fedora 201.3 KiB gnupg2-verify x86_64 0:2.4.9-18.fc45 fedora 356.3 KiB gnutls x86_64 0:3.8.13-5.fc46 fedora 3.8 MiB go-srpm-macros noarch 0:3.8.0-3.fc45 fedora 61.9 KiB gpgverify noarch 0:2.2-5.fc45 fedora 8.7 KiB ima-evm-utils-libs x86_64 0:1.6.2-12.fc45 fedora 56.6 KiB jansson x86_64 0:2.14-5.fc45 fedora 89.0 KiB java-srpm-macros noarch 0:1-9.fc45 fedora 870.0 B json-c x86_64 0:0.18-9.fc45 fedora 82.7 KiB kernel-srpm-macros noarch 0:1.0-30.fc45 fedora 1.9 KiB keyutils-libs x86_64 0:1.6.3-8.fc45 fedora 54.2 KiB krb5-libs x86_64 0:1.22.2-9.fc45 fedora 2.4 MiB libacl x86_64 0:2.4.0-2.fc45 fedora 43.9 KiB libarchive x86_64 0:3.8.9-2.fc46 fedora 1.0 MiB libassuan x86_64 0:2.5.7-6.fc45 fedora 163.9 KiB libattr x86_64 0:2.6.0-2.fc45 fedora 24.3 KiB libblkid x86_64 0:2.42.4-2.fc46 fedora 282.3 KiB libbrotli x86_64 0:1.2.1-1.fc46 fedora 865.0 KiB libcap x86_64 0:2.78-2.fc45 fedora 208.2 KiB libcap-ng x86_64 0:0.9.6-1.fc46 fedora 68.8 KiB libcbor x86_64 0:0.14.0-3.fc45 fedora 83.5 KiB libcom_err x86_64 0:1.47.4-2.fc45 fedora 63.0 KiB libcurl x86_64 0:8.23.0-1.fc46 fedora 1.1 MiB libeconf x86_64 0:0.7.9-4.fc45 fedora 64.8 KiB libevent x86_64 0:2.1.13-1.fc46 fedora 980.7 KiB libfdisk x86_64 0:2.42.4-2.fc46 fedora 392.3 KiB libffi x86_64 0:3.8.0-1.fc46 fedora 95.5 KiB libfido2 x86_64 0:1.17.0-6.fc46 fedora 256.5 KiB libfsverity x86_64 0:1.7-4.fc45 fedora 24.4 KiB libgcc x86_64 0:16.2.1-2.fc46.1 fedora 270.7 KiB libgcrypt x86_64 0:1.12.4-1.fc46 fedora 1.7 MiB libgomp x86_64 0:16.2.1-2.fc46.1 fedora 577.5 KiB libgpg-error x86_64 0:1.61-2.fc45 fedora 953.9 KiB libidn2 x86_64 0:2.3.8-4.fc45 fedora 556.4 KiB libksba x86_64 0:1.8.1-1.fc46 fedora 431.9 KiB liblastlog2 x86_64 0:2.42.4-2.fc46 fedora 37.6 KiB libmount x86_64 0:2.42.4-2.fc46 fedora 408.9 KiB libnghttp2 x86_64 0:1.69.0-6.fc46 fedora 166.1 KiB libnghttp3 x86_64 0:1.18.0-1.fc45 fedora 163.4 KiB libpfm x86_64 0:4.14.1-2.fc46 fedora 2.4 MiB libpkgconf x86_64 0:2.5.1-2.fc45 fedora 90.1 KiB libpsl x86_64 0:0.23.3-1.fc46 fedora 80.4 KiB libselinux x86_64 0:3.11-5.fc46 fedora 205.2 KiB libselinux-utils x86_64 0:3.11-5.fc46 fedora 306.0 KiB libsemanage x86_64 0:3.11-4.fc46 fedora 320.6 KiB libsepol x86_64 0:3.11-2.fc45 fedora 866.1 KiB libsmartcols x86_64 0:2.42.4-2.fc46 fedora 188.5 KiB libssh x86_64 0:0.12.2-1.fc45 fedora 725.7 KiB libssh-config noarch 0:0.12.2-1.fc45 fedora 277.0 B libstdc++ x86_64 0:16.2.1-2.fc46.1 fedora 3.1 MiB libtasn1 x86_64 0:4.21.0-2.fc45 fedora 176.6 KiB libtool-ltdl x86_64 0:2.6.2-1.fc46 fedora 70.0 KiB libunistring x86_64 0:1.1-12.fc45 fedora 1.7 MiB libusb1 x86_64 0:1.0.30-2.fc45 fedora 180.1 KiB libuuid x86_64 0:2.42.4-2.fc46 fedora 37.2 KiB libverto x86_64 0:0.3.2-13.fc45 fedora 25.3 KiB libxcrypt x86_64 0:4.5.2-4.fc45 fedora 293.2 KiB libxml2 x86_64 0:2.15.4-1.fc46 fedora 1.7 MiB libzstd x86_64 0:1.5.7-6.fc45 fedora 956.1 KiB linkdupes x86_64 0:0.7.3-3.fc45 fedora 782.1 KiB lua-libs x86_64 0:5.5.1-2.fc46 fedora 298.0 KiB lua-srpm-macros noarch 0:1-18.fc45 fedora 1.3 KiB lz4-libs x86_64 0:1.10.0-5.fc45 fedora 165.3 KiB meson-srpm-macros noarch 0:1.12.1-2.fc46 fedora 1.7 KiB mpfr x86_64 0:4.2.2-4.fc45 fedora 849.2 KiB ncurses-base noarch 0:6.6-3.fc45 fedora 329.7 KiB ncurses-libs x86_64 0:6.6-3.fc45 fedora 969.1 KiB nettle x86_64 0:4.0-5.fc45 fedora 801.9 KiB ngtcp2 x86_64 0:1.22.1-3.fc45 fedora 334.3 KiB ngtcp2-crypto-ossl x86_64 0:1.22.1-3.fc45 fedora 51.6 KiB npth x86_64 0:1.8-5.fc45 fedora 49.5 KiB ocaml-srpm-macros noarch 0:11-4.fc45 fedora 1.9 KiB openblas-srpm-macros noarch 0:2-23.fc46 fedora 124.0 B openldap x86_64 0:2.6.15-1.fc46 fedora 683.4 KiB openssl-libs x86_64 1:4.0.3-1.fc46 fedora 6.7 MiB p11-kit x86_64 0:0.26.5-1.fc45 fedora 2.6 MiB p11-kit-trust x86_64 0:0.26.5-1.fc45 fedora 478.4 KiB package-notes-srpm-macros noarch 0:0.20-2.fc45 fedora 1.6 KiB pam-libs x86_64 0:1.7.2-4.fc45 fedora 134.5 KiB pcre2 x86_64 0:10.47-1.fc45.2 fedora 718.5 KiB pcre2-syntax noarch 0:10.47-1.fc45.2 fedora 281.9 KiB perl-srpm-macros noarch 0:1-65.fc45 fedora 861.0 B pkgconf x86_64 0:2.5.1-2.fc45 fedora 92.7 KiB pkgconf-m4 noarch 0:2.5.1-2.fc45 fedora 14.3 KiB pkgconf-pkg-config x86_64 0:2.5.1-2.fc45 fedora 989.0 B policycoreutils x86_64 0:3.11-2.fc45 fedora 892.9 KiB popt x86_64 0:1.19-11.fc45 fedora 136.7 KiB publicsuffix-list-dafsa noarch 0:20260624-2.fc45 fedora 71.3 KiB pyproject-srpm-macros noarch 0:1.24.0-1.fc46 fedora 3.4 KiB python-srpm-macros noarch 0:3.15-2.fc45 fedora 51.6 KiB qt5-srpm-macros noarch 0:5.15.18-3.fc45 fedora 500.0 B qt6-srpm-macros noarch 0:6.11.2-1.fc46 fedora 472.0 B readline x86_64 0:8.3-7.fc46 fedora 515.6 KiB redhat-systemd-presets noarch 0:102-3.fc45 fedora 1.0 KiB redhat-systemd-presets-common noarch 0:102-3.fc45 fedora 16.9 KiB rpm x86_64 0:6.1.0-1.fc46 fedora 3.1 MiB rpm-build-libs x86_64 0:6.1.0-1.fc46 fedora 288.3 KiB rpm-libs x86_64 0:6.1.0-1.fc46 fedora 1.1 MiB rpm-plugin-selinux x86_64 0:6.1.0-1.fc46 fedora 11.9 KiB rpm-sequoia x86_64 0:1.10.3-1.fc46 fedora 2.4 MiB rpm-sign-libs x86_64 0:6.1.0-1.fc46 fedora 39.6 KiB rust-srpm-macros noarch 0:28.5-2.fc45 fedora 5.5 KiB selinux-policy noarch 0:45.22-1.fc46 fedora 32.1 KiB selinux-policy-targeted noarch 0:45.22-1.fc46 fedora 18.9 MiB setup noarch 0:2.15.1-2.fc45 fedora 725.6 KiB sqlite-libs x86_64 0:3.54.1-1.fc46 fedora 1.6 MiB systemd-libs x86_64 0:262.1-1.fc46 fedora 2.8 MiB systemd-standalone-sysusers x86_64 0:262.1-1.fc46 fedora 981.2 KiB tpm2-tss x86_64 0:4.2.0-1.fc45 fedora 1.7 MiB tree-sitter-srpm-macros noarch 0:0.4.6-2.fc45 fedora 8.6 KiB util-linux-core x86_64 0:2.42.4-2.fc46 fedora 1.5 MiB xxhash-libs x86_64 0:0.8.4-1.fc46 fedora 94.0 KiB xz-libs x86_64 1:5.8.4-1.fc46 fedora 221.7 KiB zig-srpm-macros noarch 0:1-9.fc45 fedora 1.3 KiB zip x86_64 0:3.0-46.fc45 fedora 694.1 KiB zlib-ng-compat x86_64 0:2.3.3-6.fc45 fedora 165.6 KiB zstd x86_64 0:1.5.7-6.fc45 fedora 502.6 KiB Installing groups: Buildsystem building group Transaction Summary: Installing: 190 packages Total size of inbound packages is 72 MiB. Need to download 72 MiB. After this operation, 231 MiB extra will be used (install 231 MiB, remove 0 B). [ 1/190] bzip2-0:1.0.8-24.fc45.x86_64 100% | 25.5 MiB/s | 52.3 KiB | 00m00s [ 2/190] bash-0:5.3.20-1.fc46.x86_64 100% | 157.6 MiB/s | 1.9 MiB | 00m00s [ 3/190] cpio-0:2.15-10.fc45.x86_64 100% | 40.8 MiB/s | 292.5 KiB | 00m00s [ 4/190] coreutils-0:9.12-1.fc46.x86_6 100% | 108.3 MiB/s | 1.3 MiB | 00m00s [ 5/190] diffutils-0:3.12-6.fc45.x86_6 100% | 129.1 MiB/s | 396.6 KiB | 00m00s [ 6/190] fedora-release-common-0:46-0. 100% | 5.9 MiB/s | 18.2 KiB | 00m00s [ 7/190] glibc-minimal-langpack-0:2.44 100% | 67.9 MiB/s | 139.0 KiB | 00m00s [ 8/190] findutils-1:4.11.0-2.fc45.x86 100% | 139.3 MiB/s | 570.7 KiB | 00m00s [ 9/190] grep-0:3.12-4.fc45.x86_64 100% | 58.8 MiB/s | 301.0 KiB | 00m00s [ 10/190] gzip-0:1.15-1.fc46.x86_64 100% | 47.2 MiB/s | 193.3 KiB | 00m00s [ 11/190] info-0:7.3-3.fc45.x86_64 100% | 62.2 MiB/s | 191.2 KiB | 00m00s [ 12/190] redhat-rpm-config-0:345-5.fc4 100% | 38.1 MiB/s | 78.1 KiB | 00m00s [ 13/190] patch-0:2.8-6.fc46.x86_64 100% | 37.2 MiB/s | 114.4 KiB | 00m00s [ 14/190] rpm-build-0:6.1.0-1.fc46.x86_ 100% | 77.2 MiB/s | 158.1 KiB | 00m00s [ 15/190] shadow-utils-2:4.20.0-2.fc46. 100% | 283.3 MiB/s | 1.4 MiB | 00m00s [ 16/190] sed-0:4.10-2.fc45.x86_64 100% | 52.5 MiB/s | 322.8 KiB | 00m00s [ 17/190] tar-2:1.35-9.fc45.x86_64 100% | 105.9 MiB/s | 867.4 KiB | 00m00s [ 18/190] which-0:2.25-2.fc45.x86_64 100% | 13.7 MiB/s | 42.2 KiB | 00m00s [ 19/190] unzip-0:6.0-71.fc45.x86_64 100% | 48.7 MiB/s | 199.6 KiB | 00m00s [ 20/190] xz-1:5.8.4-1.fc46.x86_64 100% | 159.8 MiB/s | 654.4 KiB | 00m00s [ 21/190] gawk-0:5.4.1-1.fc45.x86_64 100% | 117.8 MiB/s | 1.2 MiB | 00m00s [ 22/190] util-linux-0:2.42.4-2.fc46.x8 100% | 114.9 MiB/s | 1.3 MiB | 00m00s [ 23/190] glibc-0:2.44.9000-5.fc46.x86_ 100% | 248.6 MiB/s | 2.5 MiB | 00m00s [ 24/190] filesystem-0:3.18-59.fc45.x86 100% | 90.8 MiB/s | 1.8 MiB | 00m00s [ 25/190] ncurses-libs-0:6.6-3.fc45.x86 100% | 25.8 MiB/s | 343.7 KiB | 00m00s [ 26/190] bzip2-libs-0:1.0.8-24.fc45.x8 100% | 8.5 MiB/s | 43.5 KiB | 00m00s [ 27/190] gmp-1:6.3.0-6.fc45.x86_64 100% | 104.7 MiB/s | 321.8 KiB | 00m00s [ 28/190] libacl-0:2.4.0-2.fc45.x86_64 100% | 6.7 MiB/s | 27.5 KiB | 00m00s [ 29/190] libattr-0:2.6.0-2.fc45.x86_64 100% | 5.9 MiB/s | 18.1 KiB | 00m00s [ 30/190] coreutils-common-0:9.12-1.fc4 100% | 202.7 MiB/s | 2.2 MiB | 00m00s [ 31/190] libcap-0:2.78-2.fc45.x86_64 100% | 21.6 MiB/s | 88.6 KiB | 00m00s [ 32/190] libselinux-0:3.11-5.fc46.x86_ 100% | 25.4 MiB/s | 104.0 KiB | 00m00s [ 33/190] systemd-libs-0:262.1-1.fc46.x 100% | 188.2 MiB/s | 963.7 KiB | 00m00s [ 34/190] fedora-repos-0:46-0.3.noarch 100% | 1.9 MiB/s | 9.6 KiB | 00m00s [ 35/190] glibc-common-0:2.44.9000-5.fc 100% | 105.4 MiB/s | 431.9 KiB | 00m00s [ 36/190] redhat-systemd-presets-0:102- 100% | 2.1 MiB/s | 8.5 KiB | 00m00s [ 37/190] pcre2-0:10.47-1.fc45.2.x86_64 100% | 67.5 MiB/s | 276.7 KiB | 00m00s [ 38/190] ed-0:1.22.6-1.fc46.x86_64 100% | 20.9 MiB/s | 85.6 KiB | 00m00s [ 39/190] openssl-libs-1:4.0.3-1.fc46.x 100% | 130.1 MiB/s | 2.3 MiB | 00m00s [ 40/190] R-srpm-macros-0:1.3.7-3.fc45. 100% | 3.6 MiB/s | 11.1 KiB | 00m00s [ 41/190] ansible-srpm-macros-0:1-22.fc 100% | 6.5 MiB/s | 19.8 KiB | 00m00s [ 42/190] build-reproducibility-srpm-ma 100% | 5.3 MiB/s | 10.8 KiB | 00m00s [ 43/190] cmake-srpm-macros-0:4.3.0-5.f 100% | 5.0 MiB/s | 10.3 KiB | 00m00s [ 44/190] dwz-0:0.17-3.fc45.x86_64 100% | 45.3 MiB/s | 139.2 KiB | 00m00s [ 45/190] erlang-srpm-macros-0:0.4.0-1. 100% | 9.7 MiB/s | 10.0 KiB | 00m00s [ 46/190] efi-srpm-macros-0:6-9.fc45.no 100% | 10.5 MiB/s | 21.4 KiB | 00m00s [ 47/190] file-0:5.48-3.fc46.x86_64 100% | 16.5 MiB/s | 50.6 KiB | 00m00s [ 48/190] fonts-srpm-macros-1:5.0.0-4.f 100% | 13.3 MiB/s | 27.2 KiB | 00m00s [ 49/190] filesystem-srpm-macros-0:3.18 100% | 8.6 MiB/s | 26.4 KiB | 00m00s [ 50/190] fpc-srpm-macros-0:1.3-17.fc45 100% | 7.6 MiB/s | 7.8 KiB | 00m00s [ 51/190] forge-srpm-macros-0:0.4.0-5.f 100% | 9.6 MiB/s | 19.7 KiB | 00m00s [ 52/190] gap-srpm-macros-0:2-3.fc45.no 100% | 9.1 MiB/s | 9.3 KiB | 00m00s [ 53/190] ghc-srpm-macros-0:1.10-2.fc45 100% | 8.3 MiB/s | 8.5 KiB | 00m00s [ 54/190] gnat-srpm-macros-0:7-3.fc45.n 100% | 4.2 MiB/s | 8.6 KiB | 00m00s [ 55/190] gnome-srpm-macros-0:1.0-2.fc4 100% | 4.3 MiB/s | 8.8 KiB | 00m00s [ 56/190] kernel-srpm-macros-0:1.0-30.f 100% | 8.1 MiB/s | 8.3 KiB | 00m00s [ 57/190] java-srpm-macros-0:1-9.fc45.n 100% | 4.0 MiB/s | 8.3 KiB | 00m00s [ 58/190] go-srpm-macros-0:3.8.0-3.fc45 100% | 9.1 MiB/s | 27.8 KiB | 00m00s [ 59/190] lua-srpm-macros-0:1-18.fc45.n 100% | 8.5 MiB/s | 8.7 KiB | 00m00s [ 60/190] ocaml-srpm-macros-0:11-4.fc45 100% | 4.4 MiB/s | 9.0 KiB | 00m00s [ 61/190] meson-srpm-macros-0:1.12.1-2. 100% | 5.8 MiB/s | 11.8 KiB | 00m00s [ 62/190] openblas-srpm-macros-0:2-23.f 100% | 3.7 MiB/s | 7.5 KiB | 00m00s [ 63/190] package-notes-srpm-macros-0:0 100% | 3.4 MiB/s | 10.5 KiB | 00m00s [ 64/190] perl-srpm-macros-0:1-65.fc45. 100% | 2.7 MiB/s | 8.4 KiB | 00m00s [ 65/190] pyproject-srpm-macros-0:1.24. 100% | 3.8 MiB/s | 15.4 KiB | 00m00s [ 66/190] qt5-srpm-macros-0:5.15.18-3.f 100% | 7.9 MiB/s | 8.1 KiB | 00m00s [ 67/190] python-srpm-macros-0:3.15-2.f 100% | 11.6 MiB/s | 23.9 KiB | 00m00s [ 68/190] qt6-srpm-macros-0:6.11.2-1.fc 100% | 4.4 MiB/s | 9.1 KiB | 00m00s [ 69/190] rust-srpm-macros-0:28.5-2.fc4 100% | 5.6 MiB/s | 11.4 KiB | 00m00s [ 70/190] rpm-0:6.1.0-1.fc46.x86_64 100% | 139.5 MiB/s | 571.3 KiB | 00m00s [ 71/190] tree-sitter-srpm-macros-0:0.4 100% | 2.7 MiB/s | 14.0 KiB | 00m00s [ 72/190] zig-srpm-macros-0:1-9.fc45.no 100% | 1.4 MiB/s | 8.8 KiB | 00m00s [ 73/190] zip-0:3.0-46.fc45.x86_64 100% | 64.6 MiB/s | 264.6 KiB | 00m00s [ 74/190] elfutils-0:0.197-1.fc46.x86_6 100% | 152.7 MiB/s | 625.6 KiB | 00m00s [ 75/190] elfutils-libelf-0:0.197-1.fc4 100% | 64.9 MiB/s | 265.9 KiB | 00m00s [ 76/190] debugedit-0:5.3-3.fc45.x86_64 100% | 12.3 MiB/s | 87.9 KiB | 00m00s [ 77/190] libgcc-0:16.2.1-2.fc46.1.x86_ 100% | 66.7 MiB/s | 136.6 KiB | 00m00s [ 78/190] libarchive-0:3.8.9-2.fc46.x86 100% | 108.9 MiB/s | 446.0 KiB | 00m00s [ 79/190] libstdc++-0:16.2.1-2.fc46.1.x 100% | 166.7 MiB/s | 1.0 MiB | 00m00s [ 80/190] popt-0:1.19-11.fc45.x86_64 100% | 16.3 MiB/s | 66.6 KiB | 00m00s [ 81/190] readline-0:8.3-7.fc46.x86_64 100% | 74.4 MiB/s | 228.7 KiB | 00m00s [ 82/190] rpm-build-libs-0:6.1.0-1.fc46 100% | 65.8 MiB/s | 134.8 KiB | 00m00s [ 83/190] rpm-libs-0:6.1.0-1.fc46.x86_6 100% | 155.1 MiB/s | 476.6 KiB | 00m00s [ 84/190] zstd-0:1.5.7-6.fc45.x86_64 100% | 62.4 MiB/s | 191.7 KiB | 00m00s [ 85/190] audit-libs-0:4.2.1-2.fc45.x86 100% | 69.9 MiB/s | 143.3 KiB | 00m00s [ 86/190] libeconf-0:0.7.9-4.fc45.x86_6 100% | 17.5 MiB/s | 35.9 KiB | 00m00s [ 87/190] libsemanage-0:3.11-4.fc46.x86 100% | 63.7 MiB/s | 130.5 KiB | 00m00s [ 88/190] libxcrypt-0:4.5.2-4.fc45.x86_ 100% | 63.9 MiB/s | 130.9 KiB | 00m00s [ 89/190] pam-libs-0:1.7.2-4.fc45.x86_6 100% | 28.5 MiB/s | 58.4 KiB | 00m00s [ 90/190] setup-0:2.15.1-2.fc45.noarch 100% | 77.0 MiB/s | 157.6 KiB | 00m00s [ 91/190] xz-libs-1:5.8.4-1.fc46.x86_64 100% | 28.4 MiB/s | 116.5 KiB | 00m00s [ 92/190] mpfr-0:4.2.2-4.fc45.x86_64 100% | 58.2 MiB/s | 357.4 KiB | 00m00s [ 93/190] libblkid-0:2.42.4-2.fc46.x86_ 100% | 21.8 MiB/s | 134.0 KiB | 00m00s [ 94/190] libcap-ng-0:0.9.6-1.fc46.x86_ 100% | 11.3 MiB/s | 34.8 KiB | 00m00s [ 95/190] libfdisk-0:2.42.4-2.fc46.x86_ 100% | 82.8 MiB/s | 169.6 KiB | 00m00s [ 96/190] liblastlog2-0:2.42.4-2.fc46.x 100% | 12.2 MiB/s | 25.0 KiB | 00m00s [ 97/190] libmount-0:2.42.4-2.fc46.x86_ 100% | 58.5 MiB/s | 179.8 KiB | 00m00s [ 98/190] libsmartcols-0:2.42.4-2.fc46. 100% | 28.9 MiB/s | 88.8 KiB | 00m00s [ 99/190] libuuid-0:2.42.4-2.fc46.x86_6 100% | 13.5 MiB/s | 27.7 KiB | 00m00s [100/190] util-linux-core-0:2.42.4-2.fc 100% | 142.3 MiB/s | 582.9 KiB | 00m00s [101/190] zlib-ng-compat-0:2.3.3-6.fc45 100% | 22.1 MiB/s | 90.4 KiB | 00m00s [102/190] ncurses-base-0:6.6-3.fc45.noa 100% | 28.7 MiB/s | 88.1 KiB | 00m00s [103/190] gnulib-l10n-0:20241231-4.fc45 100% | 49.0 MiB/s | 150.4 KiB | 00m00s [104/190] glibc-gconv-extra-0:2.44.9000 100% | 155.9 MiB/s | 1.7 MiB | 00m00s [105/190] ca-certificates-0:2026.2.92_v 100% | 189.8 MiB/s | 971.9 KiB | 00m00s [106/190] libsepol-0:3.11-2.fc45.x86_64 100% | 44.6 MiB/s | 365.2 KiB | 00m00s [107/190] crypto-policies-0:20260713-2. 100% | 15.9 MiB/s | 97.5 KiB | 00m00s [108/190] fedora-gpg-keys-0:46-0.3.noar 100% | 46.8 MiB/s | 143.8 KiB | 00m00s [109/190] redhat-systemd-presets-common 100% | 6.5 MiB/s | 13.2 KiB | 00m00s [110/190] fedora-repos-rawhide-0:46-0.3 100% | 2.9 MiB/s | 9.0 KiB | 00m00s [111/190] fips-provider-0:1.5.3-1.fc46. 100% | 147.1 MiB/s | 1.6 MiB | 00m00s [112/190] pcre2-syntax-0:10.47-1.fc45.2 100% | 40.3 MiB/s | 165.1 KiB | 00m00s [113/190] add-determinism-0:0.7.3-3.fc4 100% | 137.6 MiB/s | 845.7 KiB | 00m00s [114/190] linkdupes-0:0.7.3-3.fc45.x86_ 100% | 82.8 MiB/s | 339.2 KiB | 00m00s [115/190] file-libs-0:5.48-3.fc46.x86_6 100% | 144.0 MiB/s | 884.7 KiB | 00m00s [116/190] elfutils-libs-0:0.197-1.fc46. 100% | 139.4 MiB/s | 285.6 KiB | 00m00s [117/190] curl-0:8.23.0-1.fc46.x86_64 100% | 47.9 MiB/s | 245.2 KiB | 00m00s [118/190] elfutils-debuginfod-client-0: 100% | 23.1 MiB/s | 47.4 KiB | 00m00s [119/190] json-c-0:0.18-9.fc45.x86_64 100% | 22.8 MiB/s | 46.7 KiB | 00m00s [120/190] libpfm-0:4.14.1-2.fc46.x86_64 100% | 90.5 MiB/s | 278.0 KiB | 00m00s [121/190] libzstd-0:1.5.7-6.fc45.x86_64 100% | 88.8 MiB/s | 363.9 KiB | 00m00s [122/190] lz4-libs-0:1.10.0-5.fc45.x86_ 100% | 19.6 MiB/s | 80.4 KiB | 00m00s [123/190] libxml2-0:2.15.4-1.fc46.x86_6 100% | 82.6 MiB/s | 676.7 KiB | 00m00s [124/190] libgomp-0:16.2.1-2.fc46.1.x86 100% | 55.5 MiB/s | 397.6 KiB | 00m00s [125/190] rpm-sign-libs-0:6.1.0-1.fc46. 100% | 5.3 MiB/s | 26.9 KiB | 00m00s [126/190] lua-libs-0:5.5.1-2.fc46.x86_6 100% | 20.1 MiB/s | 144.4 KiB | 00m00s [127/190] sqlite-libs-0:3.54.1-1.fc46.x 100% | 201.2 MiB/s | 824.0 KiB | 00m00s [128/190] rpm-sequoia-0:1.10.3-1.fc46.x 100% | 115.1 MiB/s | 942.6 KiB | 00m00s [129/190] ima-evm-utils-libs-0:1.6.2-12 100% | 7.4 MiB/s | 30.2 KiB | 00m00s [130/190] gnupg2-0:2.4.9-18.fc45.x86_64 100% | 150.2 MiB/s | 1.7 MiB | 00m00s [131/190] gpgverify-0:2.2-5.fc45.noarch 100% | 3.7 MiB/s | 11.3 KiB | 00m00s [132/190] libfsverity-0:1.7-4.fc45.x86_ 100% | 3.7 MiB/s | 19.0 KiB | 00m00s [133/190] gnupg2-dirmngr-0:2.4.9-18.fc4 100% | 68.7 MiB/s | 281.6 KiB | 00m00s [134/190] gnupg2-gpg-agent-0:2.4.9-18.f 100% | 68.7 MiB/s | 281.3 KiB | 00m00s [135/190] gnupg2-gpgconf-0:2.4.9-18.fc4 100% | 28.5 MiB/s | 116.5 KiB | 00m00s [136/190] gnupg2-keyboxd-0:2.4.9-18.fc4 100% | 47.2 MiB/s | 96.6 KiB | 00m00s [137/190] libassuan-0:2.5.7-6.fc45.x86_ 100% | 33.5 MiB/s | 68.5 KiB | 00m00s [138/190] gnupg2-verify-0:2.4.9-18.fc45 100% | 43.0 MiB/s | 176.1 KiB | 00m00s [139/190] libgcrypt-0:1.12.4-1.fc46.x86 100% | 154.1 MiB/s | 631.2 KiB | 00m00s [140/190] libgpg-error-0:1.61-2.fc45.x8 100% | 61.7 MiB/s | 252.9 KiB | 00m00s [141/190] npth-0:1.8-5.fc45.x86_64 100% | 8.3 MiB/s | 25.5 KiB | 00m00s [142/190] tpm2-tss-0:4.2.0-1.fc45.x86_6 100% | 111.5 MiB/s | 456.8 KiB | 00m00s [143/190] libksba-0:1.8.1-1.fc46.x86_64 100% | 42.1 MiB/s | 172.6 KiB | 00m00s [144/190] openldap-0:2.6.15-1.fc46.x86_ 100% | 66.7 MiB/s | 273.0 KiB | 00m00s [145/190] libusb1-0:1.0.30-2.fc45.x86_6 100% | 27.3 MiB/s | 83.8 KiB | 00m00s [146/190] gnutls-0:3.8.13-5.fc46.x86_64 100% | 158.0 MiB/s | 1.4 MiB | 00m00s [147/190] libidn2-0:2.3.8-4.fc45.x86_64 100% | 42.8 MiB/s | 175.2 KiB | 00m00s [148/190] libtasn1-0:4.21.0-2.fc45.x86_ 100% | 24.7 MiB/s | 75.9 KiB | 00m00s [149/190] libunistring-0:1.1-12.fc45.x8 100% | 106.6 MiB/s | 545.8 KiB | 00m00s [150/190] nettle-0:4.0-5.fc45.x86_64 100% | 83.9 MiB/s | 429.7 KiB | 00m00s [151/190] p11-kit-0:0.26.5-1.fc45.x86_6 100% | 91.1 MiB/s | 560.0 KiB | 00m00s [152/190] cyrus-sasl-lib-0:2.1.28-37.fc 100% | 99.8 MiB/s | 817.8 KiB | 00m00s [153/190] libevent-0:2.1.13-1.fc46.x86_ 100% | 47.1 MiB/s | 289.4 KiB | 00m00s [154/190] libtool-ltdl-0:2.6.2-1.fc46.x 100% | 7.2 MiB/s | 36.8 KiB | 00m00s [155/190] libffi-0:3.8.0-1.fc46.x86_64 100% | 22.7 MiB/s | 46.4 KiB | 00m00s [156/190] gdbm-libs-1:1.26-1.fc46.x86_6 100% | 29.4 MiB/s | 60.1 KiB | 00m00s [157/190] alternatives-0:1.33-6.fc45.x8 100% | 12.8 MiB/s | 39.4 KiB | 00m00s [158/190] pkgconf-pkg-config-0:2.5.1-2. 100% | 4.6 MiB/s | 9.5 KiB | 00m00s [159/190] jansson-0:2.14-5.fc45.x86_64 100% | 9.2 MiB/s | 46.9 KiB | 00m00s [160/190] pkgconf-0:2.5.1-2.fc45.x86_64 100% | 23.9 MiB/s | 49.0 KiB | 00m00s [161/190] pkgconf-m4-0:2.5.1-2.fc45.noa 100% | 6.7 MiB/s | 13.8 KiB | 00m00s [162/190] libpkgconf-0:2.5.1-2.fc45.x86 100% | 41.6 MiB/s | 42.6 KiB | 00m00s [163/190] p11-kit-trust-0:0.26.5-1.fc45 100% | 35.7 MiB/s | 146.3 KiB | 00m00s [164/190] fedora-release-0:46-0.1.noarc 100% | 3.9 MiB/s | 11.9 KiB | 00m00s [165/190] binutils-0:2.47.50-20.fc46.x8 100% | 236.9 MiB/s | 5.2 MiB | 00m00s [166/190] systemd-standalone-sysusers-0 100% | 60.6 MiB/s | 434.1 KiB | 00m00s [167/190] xxhash-libs-0:0.8.4-1.fc46.x8 100% | 10.1 MiB/s | 41.3 KiB | 00m00s [168/190] fedora-release-identity-basic 100% | 3.1 MiB/s | 12.7 KiB | 00m00s [169/190] libcurl-0:8.23.0-1.fc46.x86_6 100% | 121.5 MiB/s | 497.5 KiB | 00m00s [170/190] krb5-libs-0:1.22.2-9.fc45.x86 100% | 130.7 MiB/s | 803.1 KiB | 00m00s [171/190] libbrotli-0:1.2.1-1.fc46.x86_ 100% | 84.8 MiB/s | 347.3 KiB | 00m00s [172/190] gdb-minimal-0:18.1-1.fc46.x86 100% | 192.1 MiB/s | 4.8 MiB | 00m00s [173/190] libnghttp2-0:1.69.0-6.fc46.x8 100% | 10.8 MiB/s | 77.2 KiB | 00m00s [174/190] libnghttp3-0:1.18.0-1.fc45.x8 100% | 12.2 MiB/s | 75.1 KiB | 00m00s [175/190] libpsl-0:0.23.3-1.fc46.x86_64 100% | 33.0 MiB/s | 67.7 KiB | 00m00s [176/190] ngtcp2-0:1.22.1-3.fc45.x86_64 100% | 51.3 MiB/s | 157.7 KiB | 00m00s [177/190] libssh-0:0.12.2-1.fc45.x86_64 100% | 72.2 MiB/s | 295.9 KiB | 00m00s [178/190] ngtcp2-crypto-ossl-0:1.22.1-3 100% | 13.6 MiB/s | 27.8 KiB | 00m00s [179/190] keyutils-libs-0:1.6.3-8.fc45. 100% | 15.4 MiB/s | 31.5 KiB | 00m00s [180/190] libcom_err-0:1.47.4-2.fc45.x8 100% | 13.0 MiB/s | 26.6 KiB | 00m00s [181/190] libverto-0:0.3.2-13.fc45.x86_ 100% | 6.8 MiB/s | 21.0 KiB | 00m00s [182/190] publicsuffix-list-dafsa-0:202 100% | 19.9 MiB/s | 61.1 KiB | 00m00s [183/190] libfido2-0:1.17.0-6.fc46.x86_ 100% | 52.2 MiB/s | 107.0 KiB | 00m00s [184/190] libssh-config-0:0.12.2-1.fc45 100% | 4.4 MiB/s | 8.9 KiB | 00m00s [185/190] libcbor-0:0.14.0-3.fc45.x86_6 100% | 35.9 MiB/s | 36.8 KiB | 00m00s [186/190] policycoreutils-0:3.11-2.fc45 100% | 127.4 MiB/s | 261.0 KiB | 00m00s [187/190] selinux-policy-0:45.22-1.fc46 100% | 13.9 MiB/s | 42.8 KiB | 00m00s [188/190] libselinux-utils-0:3.11-5.fc4 100% | 40.3 MiB/s | 123.8 KiB | 00m00s [189/190] rpm-plugin-selinux-0:6.1.0-1. 100% | 8.7 MiB/s | 17.8 KiB | 00m00s [190/190] selinux-policy-targeted-0:45. 100% | 284.3 MiB/s | 6.8 MiB | 00m00s -------------------------------------------------------------------------------- [190/190] Total 100% | 207.7 MiB/s | 71.7 MiB | 00m00s Running transaction Importing OpenPGP key 0x91211FCE: UserID : "Fedora (46) " Fingerprint: D924B10D3E810DABDD8B56B596E7E91491211FCE From : file:///usr/share/distribution-gpg-keys/fedora/RPM-GPG-KEY-fedora-46-primary The key was successfully imported. Importing OpenPGP key 0x91211FCE: UserID : "Fedora (46) " Fingerprint: D924B10D3E810DABDD8B56B596E7E91491211FCE From : file:///usr/share/distribution-gpg-keys/fedora/RPM-GPG-KEY-fedora-46-primary The key was successfully imported. Importing OpenPGP key 0xF577861E: UserID : "Fedora (45) " Fingerprint: 4F50A6114CD5C6976A7F1179655A4B02F577861E From : file:///usr/share/distribution-gpg-keys/fedora/RPM-GPG-KEY-fedora-45-primary The key was successfully imported. Importing OpenPGP key 0x9488FB64: UserID : "Fedora (47) " Fingerprint: B2E766FA50CA6FA2D5ED06FC09D879E09488FB64 From : file:///usr/share/distribution-gpg-keys/fedora/RPM-GPG-KEY-fedora-47-primary The key was successfully imported. [ 1/192] Verify package files 100% | 742.0 B/s | 190.0 B | 00m00s >>> Running %pretrans scriptlet: filesystem-0:3.18-59.fc45.x86_64 >>> Finished %pretrans scriptlet: filesystem-0:3.18-59.fc45.x86_64 >>> [RPM] failed to open /var/lib/mock/fedora-rawhide-x86_64-1792824742.145479/root/etc/group for id/name lookup: No such file or directory [ 2/192] Prepare transaction 100% | 3.6 KiB/s | 190.0 B | 00m00s [ 3/192] Installing libgcc-0:16.2.1-2. 100% | 266.0 MiB/s | 272.4 KiB | 00m00s [ 4/192] Installing redhat-systemd-pre 100% | 0.0 B/s | 1.5 KiB | 00m00s [ 5/192] Installing redhat-systemd-pre 100% | 0.0 B/s | 18.1 KiB | 00m00s [ 6/192] Installing libssh-config-0:0. 100% | 0.0 B/s | 816.0 B | 00m00s [ 7/192] Installing publicsuffix-list- 100% | 0.0 B/s | 72.0 KiB | 00m00s [ 8/192] Installing fedora-release-ide 100% | 0.0 B/s | 920.0 B | 00m00s [ 9/192] Installing fedora-gpg-keys-0: 100% | 59.2 MiB/s | 181.7 KiB | 00m00s [ 10/192] Installing fedora-repos-rawhi 100% | 0.0 B/s | 2.5 KiB | 00m00s [ 11/192] Installing fedora-repos-0:46- 100% | 0.0 B/s | 5.9 KiB | 00m00s [ 12/192] Installing fedora-release-com 100% | 0.0 B/s | 8.0 KiB | 00m00s [ 13/192] Installing fedora-release-0:4 100% | 17.3 KiB/s | 124.0 B | 00m00s >>> Running sysusers scriptlet: setup-0:2.15.1-2.fc45.noarch >>> Finished sysusers scriptlet: setup-0:2.15.1-2.fc45.noarch >>> Scriptlet output: >>> Creating group 'adm' with GID 4. >>> Creating group 'audio' with GID 63. >>> Creating group 'cdrom' with GID 11. >>> Creating group 'clock' with GID 103. >>> Creating group 'dialout' with GID 18. >>> Creating group 'disk' with GID 6. >>> Creating group 'floppy' with GID 19. >>> Creating group 'ftp' with GID 50. >>> Creating group 'games' with GID 20. >>> Creating group 'input' with GID 104. >>> Creating group 'kmem' with GID 9. >>> Creating group 'kvm' with GID 36. >>> Creating group 'lock' with GID 54. >>> Creating group 'lp' with GID 7. >>> Creating group 'mail' with GID 12. >>> Creating group 'man' with GID 15. >>> Creating group 'mem' with GID 8. >>> Creating group 'nobody' with GID 65534. >>> Creating group 'render' with GID 105. >>> Creating group 'root' with GID 0. >>> Creating group 'sgx' with GID 106. >>> Creating group 'sys' with GID 3. >>> Creating group 'tape' with GID 33. >>> Creating group 'tty' with GID 5. >>> Creating group 'users' with GID 100. >>> Creating group 'utmp' with GID 22. >>> Creating group 'video' with GID 39. >>> Creating group 'wheel' with GID 10. >>> Creating user 'adm' (adm) with UID 3 and GID 4. >>> Creating group 'bin' with GID 1. >>> Creating user 'bin' (bin) with UID 1 and GID 1. >>> Creating group 'daemon' with GID 2. >>> Creating user 'daemon' (daemon) with UID 2 and GID 2. >>> Creating user 'ftp' (FTP User) with UID 14 and GID 50. >>> Creating user 'games' (games) with UID 12 and GID 100. >>> Creating user 'halt' (halt) with UID 7 and GID 0. >>> Creating user 'lp' (lp) with UID 4 and GID 7. >>> Creating user 'mail' (mail) with UID 8 and GID 12. >>> Creating user 'nobody' (Kernel Overflow User) with UID 65534 and GID 65534. >>> Creating user 'operator' (operator) with UID 11 and GID 0. >>> Creating user 'root' (Super User) with UID 0 and GID 0. >>> Creating user 'shutdown' (shutdown) with UID 6 and GID 0. >>> Creating user 'sync' (sync) with UID 5 and GID 0. >>> [ 14/192] Installing setup-0:2.15.1-2.f 100% | 42.0 MiB/s | 731.3 KiB | 00m00s >>> [RPM] /etc/hosts created as /etc/hosts.rpmnew [ 15/192] Installing filesystem-0:3.18- 100% | 2.9 MiB/s | 253.6 KiB | 00m00s [ 16/192] Installing pkgconf-m4-0:2.5.1 100% | 0.0 B/s | 14.7 KiB | 00m00s [ 17/192] Installing pcre2-syntax-0:10. 100% | 277.7 MiB/s | 284.3 KiB | 00m00s [ 18/192] Installing gnulib-l10n-0:2024 100% | 215.5 MiB/s | 661.9 KiB | 00m00s [ 19/192] Installing coreutils-common-0 100% | 444.7 MiB/s | 11.6 MiB | 00m00s [ 20/192] Installing ncurses-base-0:6.6 100% | 115.7 MiB/s | 355.3 KiB | 00m00s [ 21/192] Installing bash-0:5.3.20-1.fc 100% | 264.8 MiB/s | 8.5 MiB | 00m00s [ 22/192] Installing glibc-common-0:2.4 100% | 54.5 MiB/s | 1.0 MiB | 00m00s [ 23/192] Installing glibc-gconv-extra- 100% | 338.6 MiB/s | 7.8 MiB | 00m00s [ 24/192] Installing glibc-0:2.44.9000- 100% | 194.1 MiB/s | 7.2 MiB | 00m00s [ 25/192] Installing ncurses-libs-0:6.6 100% | 317.4 MiB/s | 974.9 KiB | 00m00s [ 26/192] Installing glibc-minimal-lang 100% | 0.0 B/s | 124.0 B | 00m00s [ 27/192] Installing zlib-ng-compat-0:2 100% | 162.5 MiB/s | 166.4 KiB | 00m00s [ 28/192] Installing bzip2-libs-0:1.0.8 100% | 0.0 B/s | 81.6 KiB | 00m00s [ 29/192] Installing libgpg-error-0:1.6 100% | 55.1 MiB/s | 959.7 KiB | 00m00s [ 30/192] Installing readline-0:8.3-7.f 100% | 252.8 MiB/s | 517.7 KiB | 00m00s [ 31/192] Installing libstdc++-0:16.2.1 100% | 440.9 MiB/s | 3.1 MiB | 00m00s [ 32/192] Installing libzstd-0:1.5.7-6. 100% | 467.5 MiB/s | 957.4 KiB | 00m00s [ 33/192] Installing elfutils-libelf-0: 100% | 545.4 MiB/s | 1.6 MiB | 00m00s [ 34/192] Installing libassuan-0:2.5.7- 100% | 161.8 MiB/s | 165.7 KiB | 00m00s [ 35/192] Installing libgcrypt-0:1.12.4 100% | 416.6 MiB/s | 1.7 MiB | 00m00s [ 36/192] Installing gmp-1:6.3.0-6.fc45 100% | 399.1 MiB/s | 817.4 KiB | 00m00s [ 37/192] Installing libacl-0:2.4.0-2.f 100% | 0.0 B/s | 44.7 KiB | 00m00s [ 38/192] Installing systemd-libs-0:262 100% | 395.7 MiB/s | 2.8 MiB | 00m00s [ 39/192] Installing libuuid-0:2.42.4-2 100% | 0.0 B/s | 38.2 KiB | 00m00s [ 40/192] Installing popt-0:1.19-11.fc4 100% | 70.0 MiB/s | 143.3 KiB | 00m00s [ 41/192] Installing xz-libs-1:5.8.4-1. 100% | 217.6 MiB/s | 222.8 KiB | 00m00s [ 42/192] Installing sqlite-libs-0:3.54 100% | 411.7 MiB/s | 1.6 MiB | 00m00s [ 43/192] Installing npth-0:1.8-5.fc45. 100% | 0.0 B/s | 50.6 KiB | 00m00s [ 44/192] Installing elfutils-libs-0:0. 100% | 352.2 MiB/s | 721.4 KiB | 00m00s [ 45/192] Installing libblkid-0:2.42.4- 100% | 276.6 MiB/s | 283.3 KiB | 00m00s [ 46/192] Installing libsepol-0:3.11-2. 100% | 423.4 MiB/s | 867.1 KiB | 00m00s [ 47/192] Installing gnupg2-gpgconf-0:2 100% | 15.6 MiB/s | 255.9 KiB | 00m00s [ 48/192] Installing pcre2-0:10.47-1.fc 100% | 351.5 MiB/s | 720.0 KiB | 00m00s [ 49/192] Installing libselinux-0:3.11- 100% | 201.6 MiB/s | 206.4 KiB | 00m00s [ 50/192] Installing grep-0:3.12-4.fc45 100% | 55.7 MiB/s | 1.0 MiB | 00m00s [ 51/192] Installing sed-0:4.10-2.fc45. 100% | 47.5 MiB/s | 874.9 KiB | 00m00s [ 52/192] Installing findutils-1:4.11.0 100% | 103.1 MiB/s | 2.0 MiB | 00m00s [ 53/192] Installing libxcrypt-0:4.5.2- 100% | 289.0 MiB/s | 295.9 KiB | 00m00s [ 54/192] Installing json-c-0:0.18-9.fc 100% | 0.0 B/s | 83.9 KiB | 00m00s [ 55/192] Installing libtasn1-0:4.21.0- 100% | 174.3 MiB/s | 178.5 KiB | 00m00s [ 56/192] Installing libunistring-0:1.1 100% | 433.6 MiB/s | 1.7 MiB | 00m00s [ 57/192] Installing libidn2-0:2.3.8-4. 100% | 68.7 MiB/s | 562.6 KiB | 00m00s [ 58/192] Installing crypto-policies-0: 100% | 38.9 MiB/s | 159.5 KiB | 00m00s [ 59/192] Installing xz-1:5.8.4-1.fc46. 100% | 71.3 MiB/s | 1.4 MiB | 00m00s [ 60/192] Installing libmount-0:2.42.4- 100% | 400.4 MiB/s | 410.0 KiB | 00m00s [ 61/192] Installing gnupg2-verify-0:2. 100% | 21.8 MiB/s | 357.7 KiB | 00m00s [ 62/192] Installing mpfr-0:4.2.2-4.fc4 100% | 277.0 MiB/s | 850.9 KiB | 00m00s [ 63/192] Installing gawk-0:5.4.1-1.fc4 100% | 111.4 MiB/s | 2.2 MiB | 00m00s [ 64/192] Installing dwz-0:0.17-3.fc45. 100% | 19.0 MiB/s | 292.5 KiB | 00m00s [ 65/192] Installing libksba-0:1.8.1-1. 100% | 424.2 MiB/s | 434.4 KiB | 00m00s [ 66/192] Installing unzip-0:6.0-71.fc4 100% | 27.2 MiB/s | 445.3 KiB | 00m00s [ 67/192] Installing file-libs-0:5.48-3 100% | 771.5 MiB/s | 12.3 MiB | 00m00s [ 68/192] Installing file-0:5.48-3.fc46 100% | 6.7 MiB/s | 103.4 KiB | 00m00s [ 69/192] Installing diffutils-0:3.12-6 100% | 82.4 MiB/s | 1.6 MiB | 00m00s [ 70/192] Installing libattr-0:2.6.0-2. 100% | 0.0 B/s | 25.2 KiB | 00m00s [ 71/192] Installing libeconf-0:0.7.9-4 100% | 64.9 MiB/s | 66.4 KiB | 00m00s [ 72/192] Installing libcap-ng-0:0.9.6- 100% | 69.0 MiB/s | 70.6 KiB | 00m00s [ 73/192] Installing audit-libs-0:4.2.1 100% | 383.9 MiB/s | 393.1 KiB | 00m00s [ 74/192] Installing pam-libs-0:1.7.2-4 100% | 133.7 MiB/s | 136.9 KiB | 00m00s [ 75/192] Installing libcap-0:2.78-2.fc 100% | 13.0 MiB/s | 213.3 KiB | 00m00s [ 76/192] Installing libsemanage-0:3.11 100% | 314.8 MiB/s | 322.4 KiB | 00m00s [ 77/192] Installing libsmartcols-0:2.4 100% | 185.2 MiB/s | 189.6 KiB | 00m00s [ 78/192] Installing lua-libs-0:5.5.1-2 100% | 292.4 MiB/s | 299.4 KiB | 00m00s [ 79/192] Installing libffi-0:3.8.0-1.f 100% | 94.6 MiB/s | 96.9 KiB | 00m00s [ 80/192] Installing p11-kit-0:0.26.5-1 100% | 119.8 MiB/s | 2.6 MiB | 00m00s [ 81/192] Installing alternatives-0:1.3 100% | 4.1 MiB/s | 63.6 KiB | 00m00s [ 82/192] Installing p11-kit-trust-0:0. 100% | 20.4 MiB/s | 480.1 KiB | 00m00s [ 83/192] Installing ngtcp2-0:1.22.1-3. 100% | 164.0 MiB/s | 335.8 KiB | 00m00s [ 84/192] Installing util-linux-core-0: 100% | 75.6 MiB/s | 1.5 MiB | 00m00s [ 85/192] Installing liblastlog2-0:2.42 100% | 7.8 MiB/s | 39.8 KiB | 00m00s [ 86/192] Installing zip-0:3.0-46.fc45. 100% | 37.9 MiB/s | 698.0 KiB | 00m00s [ 87/192] Installing gnupg2-keyboxd-0:2 100% | 39.6 MiB/s | 202.5 KiB | 00m00s [ 88/192] Installing libpsl-0:0.23.3-1. 100% | 79.6 MiB/s | 81.5 KiB | 00m00s [ 89/192] Installing tar-2:1.35-9.fc45. 100% | 129.3 MiB/s | 3.0 MiB | 00m00s [ 90/192] Installing linkdupes-0:0.7.3- 100% | 45.0 MiB/s | 783.5 KiB | 00m00s [ 91/192] Installing libselinux-utils-0 100% | 19.6 MiB/s | 320.4 KiB | 00m00s [ 92/192] Installing libfdisk-0:2.42.4- 100% | 384.0 MiB/s | 393.2 KiB | 00m00s [ 93/192] Installing fips-provider-0:1. 100% | 439.0 MiB/s | 4.8 MiB | 00m00s [ 94/192] Installing openssl-libs-1:4.0 100% | 418.7 MiB/s | 6.7 MiB | 00m00s [ 95/192] Installing coreutils-0:9.12-1 100% | 181.5 MiB/s | 6.4 MiB | 00m00s [ 96/192] Installing ca-certificates-0: 100% | 2.5 MiB/s | 2.5 MiB | 00m01s [ 97/192] Installing gzip-0:1.15-1.fc46 100% | 23.2 MiB/s | 450.7 KiB | 00m00s [ 98/192] Installing util-linux-0:2.42. 100% | 101.5 MiB/s | 3.8 MiB | 00m00s [ 99/192] Installing policycoreutils-0: 100% | 34.6 MiB/s | 921.4 KiB | 00m00s [100/192] Installing selinux-policy-0:4 100% | 1.9 MiB/s | 34.5 KiB | 00m00s [101/192] Installing selinux-policy-tar 100% | 235.9 MiB/s | 15.1 MiB | 00m00s [102/192] Installing rpm-sequoia-0:1.10 100% | 349.6 MiB/s | 2.4 MiB | 00m00s [103/192] Installing libfsverity-0:1.7- 100% | 0.0 B/s | 25.4 KiB | 00m00s [104/192] Installing libevent-0:2.1.13- 100% | 320.5 MiB/s | 984.5 KiB | 00m00s [105/192] Installing ngtcp2-crypto-ossl 100% | 0.0 B/s | 52.5 KiB | 00m00s [106/192] Installing libusb1-0:1.0.30-2 100% | 16.1 MiB/s | 181.8 KiB | 00m00s >>> Running sysusers scriptlet: tpm2-tss-0:4.2.0-1.fc45.x86_64 >>> Finished sysusers scriptlet: tpm2-tss-0:4.2.0-1.fc45.x86_64 >>> Scriptlet output: >>> Creating group 'tss' with GID 59. >>> Creating user 'tss' (Account used for TPM access) with UID 59 and GID 59. >>> [107/192] Installing tpm2-tss-0:4.2.0-1 100% | 333.5 MiB/s | 1.7 MiB | 00m00s [108/192] Installing ima-evm-utils-libs 100% | 0.0 B/s | 57.9 KiB | 00m00s [109/192] Installing gnupg2-gpg-agent-0 100% | 29.0 MiB/s | 682.8 KiB | 00m00s [110/192] Installing nettle-0:4.0-5.fc4 100% | 262.0 MiB/s | 805.0 KiB | 00m00s [111/192] Installing gnutls-0:3.8.13-5. 100% | 426.4 MiB/s | 3.8 MiB | 00m00s [112/192] Installing zstd-0:1.5.7-6.fc4 100% | 29.1 MiB/s | 506.1 KiB | 00m00s [113/192] Installing libxml2-0:2.15.4-1 100% | 87.1 MiB/s | 1.7 MiB | 00m00s [114/192] Installing bzip2-0:1.0.8-24.f 100% | 6.1 MiB/s | 99.5 KiB | 00m00s [115/192] Installing add-determinism-0: 100% | 107.9 MiB/s | 2.2 MiB | 00m00s [116/192] Installing build-reproducibil 100% | 0.0 B/s | 1.5 KiB | 00m00s [117/192] Installing cpio-0:2.15-10.fc4 100% | 61.3 MiB/s | 1.1 MiB | 00m00s [118/192] Installing ed-0:1.22.6-1.fc46 100% | 10.0 MiB/s | 153.2 KiB | 00m00s [119/192] Installing patch-0:2.8-6.fc46 100% | 14.9 MiB/s | 228.1 KiB | 00m00s [120/192] Installing libpfm-0:4.14.1-2. 100% | 593.1 MiB/s | 2.4 MiB | 00m00s [121/192] Installing lz4-libs-0:1.10.0- 100% | 162.5 MiB/s | 166.4 KiB | 00m00s [122/192] Installing libarchive-0:3.8.9 100% | 327.4 MiB/s | 1.0 MiB | 00m00s [123/192] Installing libgomp-0:16.2.1-2 100% | 282.7 MiB/s | 578.9 KiB | 00m00s [124/192] Installing libtool-ltdl-0:2.6 100% | 0.0 B/s | 71.1 KiB | 00m00s [125/192] Installing gdbm-libs-1:1.26-1 100% | 132.7 MiB/s | 135.9 KiB | 00m00s [126/192] Installing cyrus-sasl-lib-0:2 100% | 116.9 MiB/s | 2.3 MiB | 00m00s [127/192] Installing openldap-0:2.6.15- 100% | 335.6 MiB/s | 687.2 KiB | 00m00s [128/192] Installing gnupg2-dirmngr-0:2 100% | 28.1 MiB/s | 632.8 KiB | 00m00s [129/192] Installing gnupg2-0:2.4.9-18. 100% | 216.7 MiB/s | 6.5 MiB | 00m00s [130/192] Installing gpgverify-0:2.2-5. 100% | 0.0 B/s | 9.4 KiB | 00m00s [131/192] Installing jansson-0:2.14-5.f 100% | 88.2 MiB/s | 90.3 KiB | 00m00s [132/192] Installing libpkgconf-0:2.5.1 100% | 89.1 MiB/s | 91.3 KiB | 00m00s [133/192] Installing pkgconf-0:2.5.1-2. 100% | 6.2 MiB/s | 95.2 KiB | 00m00s [134/192] Installing pkgconf-pkg-config 100% | 118.2 KiB/s | 1.8 KiB | 00m00s [135/192] Installing systemd-standalone 100% | 56.4 MiB/s | 981.8 KiB | 00m00s [136/192] Installing rpm-libs-0:6.1.0-1 100% | 366.4 MiB/s | 1.1 MiB | 00m00s [137/192] Installing rpm-sign-libs-0:6. 100% | 0.0 B/s | 40.5 KiB | 00m00s [138/192] Installing rpm-build-libs-0:6 100% | 282.4 MiB/s | 289.2 KiB | 00m00s [139/192] Installing xxhash-libs-0:0.8. 100% | 93.1 MiB/s | 95.4 KiB | 00m00s [140/192] Installing libbrotli-0:1.2.1- 100% | 282.3 MiB/s | 867.3 KiB | 00m00s [141/192] Installing libnghttp2-0:1.69. 100% | 163.3 MiB/s | 167.3 KiB | 00m00s [142/192] Installing libnghttp3-0:1.18. 100% | 161.0 MiB/s | 164.8 KiB | 00m00s [143/192] Installing keyutils-libs-0:1. 100% | 0.0 B/s | 55.6 KiB | 00m00s [144/192] Installing libcom_err-0:1.47. 100% | 0.0 B/s | 64.1 KiB | 00m00s [145/192] Installing libverto-0:0.3.2-1 100% | 26.4 MiB/s | 27.1 KiB | 00m00s [146/192] Installing krb5-libs-0:1.22.2 100% | 341.0 MiB/s | 2.4 MiB | 00m00s [147/192] Installing libcbor-0:0.14.0-3 100% | 82.9 MiB/s | 84.9 KiB | 00m00s [148/192] Installing libfido2-0:1.17.0- 100% | 252.0 MiB/s | 258.1 KiB | 00m00s [149/192] Installing libssh-0:0.12.2-1. 100% | 355.4 MiB/s | 727.8 KiB | 00m00s [150/192] Installing libcurl-0:8.23.0-1 100% | 361.9 MiB/s | 1.1 MiB | 00m00s [151/192] Installing elfutils-debuginfo 100% | 5.4 MiB/s | 82.2 KiB | 00m00s [152/192] Installing elfutils-0:0.197-1 100% | 139.6 MiB/s | 3.1 MiB | 00m00s [153/192] Installing binutils-0:2.47.50 100% | 331.4 MiB/s | 24.5 MiB | 00m00s [154/192] Installing gdb-minimal-0:18.1 100% | 300.8 MiB/s | 14.4 MiB | 00m00s [155/192] Installing debugedit-0:5.3-3. 100% | 13.7 MiB/s | 224.1 KiB | 00m00s [156/192] Installing curl-0:8.23.0-1.fc 100% | 19.9 MiB/s | 488.7 KiB | 00m00s [157/192] Installing rpm-0:6.1.0-1.fc46 100% | 78.2 MiB/s | 2.5 MiB | 00m00s [158/192] Installing cmake-srpm-macros- 100% | 0.0 B/s | 804.0 B | 00m00s [159/192] Installing efi-srpm-macros-0: 100% | 0.0 B/s | 41.3 KiB | 00m00s [160/192] Installing java-srpm-macros-0 100% | 280.3 KiB/s | 1.1 KiB | 00m00s [161/192] Installing lua-srpm-macros-0: 100% | 0.0 B/s | 1.9 KiB | 00m00s [162/192] Installing tree-sitter-srpm-m 100% | 0.0 B/s | 9.6 KiB | 00m00s [163/192] Installing zig-srpm-macros-0: 100% | 0.0 B/s | 1.9 KiB | 00m00s [164/192] Installing filesystem-srpm-ma 100% | 0.0 B/s | 38.9 KiB | 00m00s [165/192] Installing rust-srpm-macros-0 100% | 0.0 B/s | 6.4 KiB | 00m00s [166/192] Installing qt6-srpm-macros-0: 100% | 0.0 B/s | 748.0 B | 00m00s [167/192] Installing qt5-srpm-macros-0: 100% | 0.0 B/s | 776.0 B | 00m00s [168/192] Installing perl-srpm-macros-0 100% | 0.0 B/s | 1.1 KiB | 00m00s [169/192] Installing package-notes-srpm 100% | 0.0 B/s | 2.1 KiB | 00m00s [170/192] Installing openblas-srpm-macr 100% | 0.0 B/s | 404.0 B | 00m00s [171/192] Installing ocaml-srpm-macros- 100% | 0.0 B/s | 2.1 KiB | 00m00s [172/192] Installing meson-srpm-macros- 100% | 0.0 B/s | 1.9 KiB | 00m00s [173/192] Installing kernel-srpm-macros 100% | 0.0 B/s | 2.3 KiB | 00m00s [174/192] Installing gnome-srpm-macros- 100% | 0.0 B/s | 4.1 KiB | 00m00s [175/192] Installing gnat-srpm-macros-0 100% | 0.0 B/s | 1.3 KiB | 00m00s [176/192] Installing ghc-srpm-macros-0: 100% | 0.0 B/s | 1.0 KiB | 00m00s [177/192] Installing gap-srpm-macros-0: 100% | 0.0 B/s | 2.7 KiB | 00m00s [178/192] Installing fpc-srpm-macros-0: 100% | 0.0 B/s | 420.0 B | 00m00s [179/192] Installing ansible-srpm-macro 100% | 0.0 B/s | 36.2 KiB | 00m00s [180/192] Installing redhat-rpm-config- 100% | 186.0 MiB/s | 190.5 KiB | 00m00s [181/192] Installing forge-srpm-macros- 100% | 0.0 B/s | 40.3 KiB | 00m00s [182/192] Installing rpm-build-0:6.1.0- 100% | 18.5 MiB/s | 322.1 KiB | 00m00s [183/192] Installing erlang-srpm-macros 100% | 0.0 B/s | 2.6 KiB | 00m00s [184/192] Installing pyproject-srpm-mac 100% | 0.0 B/s | 4.0 KiB | 00m00s [185/192] Installing fonts-srpm-macros- 100% | 0.0 B/s | 57.0 KiB | 00m00s [186/192] Installing go-srpm-macros-0:3 100% | 0.0 B/s | 63.0 KiB | 00m00s [187/192] Installing R-srpm-macros-0:1. 100% | 0.0 B/s | 4.4 KiB | 00m00s [188/192] Installing python-srpm-macros 100% | 0.0 B/s | 52.9 KiB | 00m00s [189/192] Installing rpm-plugin-selinux 100% | 0.0 B/s | 12.9 KiB | 00m00s [190/192] Installing which-0:2.25-2.fc4 100% | 5.2 MiB/s | 85.8 KiB | 00m00s [191/192] Installing shadow-utils-2:4.2 100% | 136.1 MiB/s | 3.9 MiB | 00m00s [192/192] Installing info-0:7.3-3.fc45. 100% | 60.0 KiB/s | 372.8 KiB | 00m06s Complete! Finish: installing minimal buildroot with dnf5 Start: creating root cache Finish: creating root cache Finish: chroot init INFO: Installed packages: INFO: R-srpm-macros-1.3.7-3.fc45.noarch add-determinism-0.7.3-3.fc45.x86_64 alternatives-1.33-6.fc45.x86_64 ansible-srpm-macros-1-22.fc45.noarch audit-libs-4.2.1-2.fc45.x86_64 bash-5.3.20-1.fc46.x86_64 binutils-2.47.50-20.fc46.x86_64 build-reproducibility-srpm-macros-0.7.3-3.fc45.noarch bzip2-1.0.8-24.fc45.x86_64 bzip2-libs-1.0.8-24.fc45.x86_64 ca-certificates-2026.2.92_v9.0.319-2.fc46.noarch cmake-srpm-macros-4.3.0-5.fc45.noarch coreutils-9.12-1.fc46.x86_64 coreutils-common-9.12-1.fc46.x86_64 cpio-2.15-10.fc45.x86_64 crypto-policies-20260713-2.gitc42da77.fc45.noarch curl-8.23.0-1.fc46.x86_64 cyrus-sasl-lib-2.1.28-37.fc45.x86_64 debugedit-5.3-3.fc45.x86_64 diffutils-3.12-6.fc45.x86_64 dwz-0.17-3.fc45.x86_64 ed-1.22.6-1.fc46.x86_64 efi-srpm-macros-6-9.fc45.noarch elfutils-0.197-1.fc46.x86_64 elfutils-debuginfod-client-0.197-1.fc46.x86_64 elfutils-libelf-0.197-1.fc46.x86_64 elfutils-libs-0.197-1.fc46.x86_64 erlang-srpm-macros-0.4.0-1.fc46.noarch fedora-gpg-keys-46-0.3.noarch fedora-release-46-0.1.noarch fedora-release-common-46-0.1.noarch fedora-release-identity-basic-46-0.1.noarch fedora-repos-46-0.3.noarch fedora-repos-rawhide-46-0.3.noarch file-5.48-3.fc46.x86_64 file-libs-5.48-3.fc46.x86_64 filesystem-3.18-59.fc45.x86_64 filesystem-srpm-macros-3.18-59.fc45.noarch findutils-4.11.0-2.fc45.x86_64 fips-provider-1.5.3-1.fc46.x86_64 fonts-srpm-macros-5.0.0-4.fc45.noarch forge-srpm-macros-0.4.0-5.fc45.noarch fpc-srpm-macros-1.3-17.fc45.noarch gap-srpm-macros-2-3.fc45.noarch gawk-5.4.1-1.fc45.x86_64 gdb-minimal-18.1-1.fc46.x86_64 gdbm-libs-1.26-1.fc46.x86_64 ghc-srpm-macros-1.10-2.fc45.noarch glibc-2.44.9000-5.fc46.x86_64 glibc-common-2.44.9000-5.fc46.x86_64 glibc-gconv-extra-2.44.9000-5.fc46.x86_64 glibc-minimal-langpack-2.44.9000-5.fc46.x86_64 gmp-6.3.0-6.fc45.x86_64 gnat-srpm-macros-7-3.fc45.noarch gnome-srpm-macros-1.0-2.fc45.noarch gnulib-l10n-20241231-4.fc45.noarch gnupg2-2.4.9-18.fc45.x86_64 gnupg2-dirmngr-2.4.9-18.fc45.x86_64 gnupg2-gpg-agent-2.4.9-18.fc45.x86_64 gnupg2-gpgconf-2.4.9-18.fc45.x86_64 gnupg2-keyboxd-2.4.9-18.fc45.x86_64 gnupg2-verify-2.4.9-18.fc45.x86_64 gnutls-3.8.13-5.fc46.x86_64 go-srpm-macros-3.8.0-3.fc45.noarch gpg-pubkey-4f50a6114cd5c6976a7f1179655a4b02f577861e-6888bc98 gpg-pubkey-b2e766fa50ca6fa2d5ed06fc09d879e09488fb64-6a6b46b4 gpg-pubkey-d924b10d3e810dabdd8b56b596e7e91491211fce-697c9899 gpgverify-2.2-5.fc45.noarch grep-3.12-4.fc45.x86_64 gzip-1.15-1.fc46.x86_64 ima-evm-utils-libs-1.6.2-12.fc45.x86_64 info-7.3-3.fc45.x86_64 jansson-2.14-5.fc45.x86_64 java-srpm-macros-1-9.fc45.noarch json-c-0.18-9.fc45.x86_64 kernel-srpm-macros-1.0-30.fc45.noarch keyutils-libs-1.6.3-8.fc45.x86_64 krb5-libs-1.22.2-9.fc45.x86_64 libacl-2.4.0-2.fc45.x86_64 libarchive-3.8.9-2.fc46.x86_64 libassuan-2.5.7-6.fc45.x86_64 libattr-2.6.0-2.fc45.x86_64 libblkid-2.42.4-2.fc46.x86_64 libbrotli-1.2.1-1.fc46.x86_64 libcap-2.78-2.fc45.x86_64 libcap-ng-0.9.6-1.fc46.x86_64 libcbor-0.14.0-3.fc45.x86_64 libcom_err-1.47.4-2.fc45.x86_64 libcurl-8.23.0-1.fc46.x86_64 libeconf-0.7.9-4.fc45.x86_64 libevent-2.1.13-1.fc46.x86_64 libfdisk-2.42.4-2.fc46.x86_64 libffi-3.8.0-1.fc46.x86_64 libfido2-1.17.0-6.fc46.x86_64 libfsverity-1.7-4.fc45.x86_64 libgcc-16.2.1-2.fc46.1.x86_64 libgcrypt-1.12.4-1.fc46.x86_64 libgomp-16.2.1-2.fc46.1.x86_64 libgpg-error-1.61-2.fc45.x86_64 libidn2-2.3.8-4.fc45.x86_64 libksba-1.8.1-1.fc46.x86_64 liblastlog2-2.42.4-2.fc46.x86_64 libmount-2.42.4-2.fc46.x86_64 libnghttp2-1.69.0-6.fc46.x86_64 libnghttp3-1.18.0-1.fc45.x86_64 libpfm-4.14.1-2.fc46.x86_64 libpkgconf-2.5.1-2.fc45.x86_64 libpsl-0.23.3-1.fc46.x86_64 libselinux-3.11-5.fc46.x86_64 libselinux-utils-3.11-5.fc46.x86_64 libsemanage-3.11-4.fc46.x86_64 libsepol-3.11-2.fc45.x86_64 libsmartcols-2.42.4-2.fc46.x86_64 libssh-0.12.2-1.fc45.x86_64 libssh-config-0.12.2-1.fc45.noarch libstdc++-16.2.1-2.fc46.1.x86_64 libtasn1-4.21.0-2.fc45.x86_64 libtool-ltdl-2.6.2-1.fc46.x86_64 libunistring-1.1-12.fc45.x86_64 libusb1-1.0.30-2.fc45.x86_64 libuuid-2.42.4-2.fc46.x86_64 libverto-0.3.2-13.fc45.x86_64 libxcrypt-4.5.2-4.fc45.x86_64 libxml2-2.15.4-1.fc46.x86_64 libzstd-1.5.7-6.fc45.x86_64 linkdupes-0.7.3-3.fc45.x86_64 lua-libs-5.5.1-2.fc46.x86_64 lua-srpm-macros-1-18.fc45.noarch lz4-libs-1.10.0-5.fc45.x86_64 meson-srpm-macros-1.12.1-2.fc46.noarch mpfr-4.2.2-4.fc45.x86_64 ncurses-base-6.6-3.fc45.noarch ncurses-libs-6.6-3.fc45.x86_64 nettle-4.0-5.fc45.x86_64 ngtcp2-1.22.1-3.fc45.x86_64 ngtcp2-crypto-ossl-1.22.1-3.fc45.x86_64 npth-1.8-5.fc45.x86_64 ocaml-srpm-macros-11-4.fc45.noarch openblas-srpm-macros-2-23.fc46.noarch openldap-2.6.15-1.fc46.x86_64 openssl-libs-4.0.3-1.fc46.x86_64 p11-kit-0.26.5-1.fc45.x86_64 p11-kit-trust-0.26.5-1.fc45.x86_64 package-notes-srpm-macros-0.20-2.fc45.noarch pam-libs-1.7.2-4.fc45.x86_64 patch-2.8-6.fc46.x86_64 pcre2-10.47-1.fc45.2.x86_64 pcre2-syntax-10.47-1.fc45.2.noarch perl-srpm-macros-1-65.fc45.noarch pkgconf-2.5.1-2.fc45.x86_64 pkgconf-m4-2.5.1-2.fc45.noarch pkgconf-pkg-config-2.5.1-2.fc45.x86_64 policycoreutils-3.11-2.fc45.x86_64 popt-1.19-11.fc45.x86_64 publicsuffix-list-dafsa-20260624-2.fc45.noarch pyproject-srpm-macros-1.24.0-1.fc46.noarch python-srpm-macros-3.15-2.fc45.noarch qt5-srpm-macros-5.15.18-3.fc45.noarch qt6-srpm-macros-6.11.2-1.fc46.noarch readline-8.3-7.fc46.x86_64 redhat-rpm-config-345-5.fc46.noarch redhat-systemd-presets-102-3.fc45.noarch redhat-systemd-presets-common-102-3.fc45.noarch rpm-6.1.0-1.fc46.x86_64 rpm-build-6.1.0-1.fc46.x86_64 rpm-build-libs-6.1.0-1.fc46.x86_64 rpm-libs-6.1.0-1.fc46.x86_64 rpm-plugin-selinux-6.1.0-1.fc46.x86_64 rpm-sequoia-1.10.3-1.fc46.x86_64 rpm-sign-libs-6.1.0-1.fc46.x86_64 rust-srpm-macros-28.5-2.fc45.noarch sed-4.10-2.fc45.x86_64 selinux-policy-45.22-1.fc46.noarch selinux-policy-targeted-45.22-1.fc46.noarch setup-2.15.1-2.fc45.noarch shadow-utils-4.20.0-2.fc46.x86_64 sqlite-libs-3.54.1-1.fc46.x86_64 systemd-libs-262.1-1.fc46.x86_64 systemd-standalone-sysusers-262.1-1.fc46.x86_64 tar-1.35-9.fc45.x86_64 tpm2-tss-4.2.0-1.fc45.x86_64 tree-sitter-srpm-macros-0.4.6-2.fc45.noarch unzip-6.0-71.fc45.x86_64 util-linux-2.42.4-2.fc46.x86_64 util-linux-core-2.42.4-2.fc46.x86_64 which-2.25-2.fc45.x86_64 xxhash-libs-0.8.4-1.fc46.x86_64 xz-5.8.4-1.fc46.x86_64 xz-libs-5.8.4-1.fc46.x86_64 zig-srpm-macros-1-9.fc45.noarch zip-3.0-46.fc45.x86_64 zlib-ng-compat-2.3.3-6.fc45.x86_64 zstd-1.5.7-6.fc45.x86_64 Start: buildsrpm Start: rpmbuild -bs Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1792713600 Wrote: /builddir/build/SRPMS/python-sbmlutils-0.17.0-1.fc46.src.rpm Finish: rpmbuild -bs INFO: chroot_scan: 1 files copied to /var/lib/copr-rpmbuild/results/chroot_scan INFO: /var/lib/mock/fedora-rawhide-x86_64-1792824742.145479/root/var/log/dnf5.log INFO: chroot_scan: creating tarball /var/lib/copr-rpmbuild/results/chroot_scan.tar.gz /bin/tar: Removing leading `/' from member names Finish: buildsrpm INFO: Done(/var/lib/copr-rpmbuild/workspace/workdir-0bdhkoy4/python-sbmlutils/python-sbmlutils.spec) Config(child) 0 minutes 21 seconds INFO: Results and/or logs in: /var/lib/copr-rpmbuild/results INFO: Cleaning up build root ('cleanup_on_success=True') Start: clean chroot INFO: unmounting tmpfs. Finish: clean chroot INFO: Start(/var/lib/copr-rpmbuild/results/python-sbmlutils-0.17.0-1.fc46.src.rpm) Config(fedora-rawhide-x86_64) Start(bootstrap): chroot init INFO: mounting tmpfs at /var/lib/mock/fedora-rawhide-x86_64-bootstrap-1792824742.145479/root. INFO: reusing tmpfs at /var/lib/mock/fedora-rawhide-x86_64-bootstrap-1792824742.145479/root. INFO: calling preinit hooks INFO: enabled root cache INFO: enabled package manager cache Start(bootstrap): cleaning package manager metadata Finish(bootstrap): cleaning package manager metadata Finish(bootstrap): chroot init Start: chroot init INFO: mounting tmpfs at /var/lib/mock/fedora-rawhide-x86_64-1792824742.145479/root. INFO: calling preinit hooks INFO: enabled root cache Start: unpacking root cache Finish: unpacking root cache INFO: enabled package manager cache Start: cleaning package manager metadata Finish: cleaning package manager metadata INFO: enabled HW Info plugin INFO: Buildroot is handled by package management downloaded with a bootstrap image: rpm-6.1.0-1.fc46.x86_64 rpm-sequoia-1.10.3-1.fc46.x86_64 dnf5-5.4.6.0-1.fc46.x86_64 dnf5-plugins-5.4.6.0-1.fc46.x86_64 Finish: chroot init Start: build phase for python-sbmlutils-0.17.0-1.fc46.src.rpm Start: build setup for python-sbmlutils-0.17.0-1.fc46.src.rpm Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1792713600 Wrote: /builddir/build/SRPMS/python-sbmlutils-0.17.0-1.fc46.src.rpm Updating and loading repositories: fedora 100% | 163.8 KiB/s | 22.4 KiB | 00m00s Additional repo copr_mhough_neurofedor 100% | 12.8 KiB/s | 1.5 KiB | 00m00s Copr repository 100% | 13.0 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package Arch Version Repository Size Installing: pyproject-rpm-macros noarch 0:1.24.0-1.fc46 fedora 169.0 KiB python3-devel x86_64 0:3.15.0-1.fc46 fedora 2.5 MiB python3-libsbml x86_64 0:5.21.2-100.fc46.biofedora copr_base 34.5 MiB python3-matplotlib x86_64 0:3.11.1-2.fc45 fedora 34.5 MiB python3-pytest noarch 0:9.1.1-1.fc45 fedora 24.3 MiB python3-roadrunner x86_64 0:2.10.0-11.fc46 copr_base 12.1 MiB Installing dependencies: blas x86_64 0:3.12.0-12.fc45 fedora 1.4 MiB cairo x86_64 0:1.18.6-1.fc46 fedora 1.8 MiB default-fonts-core-sans noarch 0:4.3-4.fc46 fedora 11.9 KiB dejavu-sans-fonts noarch 0:2.37-30.fc45 fedora 5.5 MiB expat x86_64 0:2.9.0-1.fc46 fedora 349.6 KiB flexiblas x86_64 0:3.5.0-4.fc46 fedora 38.0 KiB flexiblas-netlib x86_64 0:3.5.0-4.fc46 fedora 16.3 MiB flexiblas-openblas-openmp x86_64 0:3.5.0-4.fc46 fedora 39.1 KiB fontconfig x86_64 0:2.18.3-3.fc46 fedora 1.0 MiB fonts-filesystem noarch 1:5.0.0-4.fc45 fedora 0.0 B freetype x86_64 0:2.15.0-1.fc46 fedora 946.8 KiB fribidi x86_64 0:1.0.17-2.fc46 fedora 394.5 KiB glib2 x86_64 0:2.90.1-1.fc46 fedora 15.7 MiB google-noto-fonts-common noarch 0:20261001-1.fc46 fedora 17.7 KiB google-noto-sans-vf-fonts noarch 0:20261001-1.fc46 fedora 1.4 MiB graphite2 x86_64 0:1.3.14-22.fc45 fedora 191.4 KiB harfbuzz x86_64 0:14.5.1-1.fc46 fedora 3.0 MiB jbigkit-libs x86_64 0:2.1-34.fc45 fedora 117.2 KiB lapack x86_64 0:3.12.0-12.fc45 fedora 16.4 MiB lcms2 x86_64 0:2.16-8.fc45 fedora 445.8 KiB libX11 x86_64 0:1.8.13-3.fc46 fedora 1.3 MiB libX11-common noarch 0:1.8.13-3.fc46 fedora 1.1 MiB libXau x86_64 0:1.0.12-5.fc45 fedora 72.8 KiB libXext x86_64 0:1.3.6-6.fc45 fedora 89.9 KiB libXrender x86_64 0:0.9.12-5.fc45 fedora 49.9 KiB libedit x86_64 0:3.1-60.20260512cvs.fc45 fedora 248.3 KiB libgfortran x86_64 0:16.2.1-2.fc46.1 fedora 3.4 MiB libimagequant x86_64 0:4.1.0-4.fc46 fedora 687.5 KiB libjpeg-turbo x86_64 0:3.1.4.1-2.fc45 fedora 821.8 KiB liblerc x86_64 0:4.2.0-1.fc45 fedora 661.1 KiB libpng x86_64 2:1.6.58-2.fc45 fedora 253.7 KiB libqhull_r x86_64 1:8.0.2-10.fc45 fedora 487.2 KiB libquadmath x86_64 0:16.2.1-2.fc46.1 fedora 321.9 KiB libraqm x86_64 0:0.10.1-5.fc45 fedora 32.5 KiB libsbml x86_64 0:5.21.2-100.fc46.biofedora copr_base 10.5 MiB libtiff x86_64 0:4.7.2-3.fc46 fedora 644.5 KiB libwebp x86_64 0:1.6.0-4.fc45 fedora 968.1 KiB libxcb x86_64 0:1.17.0-8.fc45 fedora 1.1 MiB llvm14-libs x86_64 0:14.0.5-15.fc45 fedora 96.0 MiB lzo x86_64 0:2.10-17.fc45 fedora 178.8 KiB minizip-ng-compat x86_64 0:4.1.0-5.fc45 fedora 146.1 KiB mpdecimal x86_64 0:4.0.1-4.fc45 fedora 221.2 KiB openblas x86_64 0:0.3.34-1.fc45 fedora 138.1 KiB openblas-openmp x86_64 0:0.3.34-1.fc45 fedora 44.8 MiB openjpeg x86_64 0:2.5.4-4.fc45 fedora 464.2 KiB pixman x86_64 0:0.46.2-4.fc45 fedora 718.3 KiB poco-foundation x86_64 0:1.14.1-3.fc44 fedora 2.3 MiB poco-net x86_64 0:1.14.1-3.fc44 fedora 1.5 MiB python-pip-wheel noarch 0:26.2.1-1.fc46 fedora 1.3 MiB python-rpm-macros noarch 0:3.15-2.fc45 fedora 28.0 KiB python3 x86_64 0:3.15.0-1.fc46 fedora 28.7 KiB python3-cairo x86_64 0:1.28.0-8.fc45 fedora 510.9 KiB python3-contourpy x86_64 0:1.4.0-1.fc46 fedora 928.0 KiB python3-cycler noarch 0:0.11.0-22.fc45 fedora 38.1 KiB python3-dateutil noarch 1:2.9.0.post0-16.fc46 fedora 877.2 KiB python3-fonttools x86_64 0:4.67.0-1.fc46 fedora 20.1 MiB python3-iniconfig noarch 0:2.3.0-5.fc45 fedora 49.6 KiB python3-kiwisolver x86_64 0:1.5.1-1.fc46 fedora 157.9 KiB python3-libs x86_64 0:3.15.0-1.fc46 fedora 48.3 MiB python3-matplotlib-data-fonts x86_64 0:3.11.1-2.fc45 fedora 8.5 MiB python3-numpy x86_64 1:2.5.4-2.fc46 fedora 43.1 MiB python3-numpy-f2py x86_64 1:2.5.4-2.fc46 fedora 2.1 MiB python3-olefile noarch 0:0.47-15.fc45 fedora 347.3 KiB python3-packaging noarch 0:26.3-1.fc46 fedora 1.3 MiB python3-pillow x86_64 0:13.0.0-1.fc46 fedora 4.6 MiB python3-pluggy noarch 0:1.7.0-1.fc46 fedora 246.1 KiB python3-pygments noarch 0:2.20.0-5.fc45 fedora 11.3 MiB python3-pyparsing noarch 0:3.1.2-19.fc46 fedora 1.0 MiB python3-rpm-generators noarch 0:14-35.fc46 fedora 81.9 KiB python3-rpm-macros noarch 0:3.15-2.fc45 fedora 6.5 KiB rr-libstruct x86_64 0:2.9.2-0.4.git7ff1f47.fc46 copr_base 254.9 KiB tzdata noarch 0:2026e-1.fc46 fedora 1.3 MiB utf8proc x86_64 0:2.11.3-3.fc45 fedora 373.5 KiB xml-common noarch 0:0.6.3-70.fc46 fedora 78.4 KiB Transaction Summary: Installing: 80 packages Total size of inbound packages is 116 MiB. Need to download 116 MiB. After this operation, 489 MiB extra will be used (install 489 MiB, remove 0 B). [ 1/80] pyproject-rpm-macros-0:1.24.0-1 100% | 14.2 MiB/s | 58.0 KiB | 00m00s [ 2/80] python3-pytest-0:9.1.1-1.fc45.n 100% | 166.7 MiB/s | 2.5 MiB | 00m00s [ 3/80] python3-devel-0:3.15.0-1.fc46.x 100% | 67.4 MiB/s | 483.0 KiB | 00m00s [ 4/80] python3-matplotlib-0:3.11.1-2.f 100% | 139.5 MiB/s | 8.5 MiB | 00m00s [ 5/80] python-rpm-macros-0:3.15-2.fc45 100% | 9.7 MiB/s | 19.8 KiB | 00m00s [ 6/80] python3-rpm-macros-0:3.15-2.fc4 100% | 6.0 MiB/s | 12.2 KiB | 00m00s [ 7/80] dejavu-sans-fonts-0:2.37-30.fc4 100% | 147.3 MiB/s | 1.3 MiB | 00m00s [ 8/80] freetype-0:2.15.0-1.fc46.x86_64 100% | 149.2 MiB/s | 458.5 KiB | 00m00s [ 9/80] libqhull_r-1:8.0.2-10.fc45.x86_ 100% | 100.5 MiB/s | 205.8 KiB | 00m00s [10/80] libraqm-0:0.10.1-5.fc45.x86_64 100% | 11.2 MiB/s | 22.8 KiB | 00m00s [11/80] python3-contourpy-0:1.4.0-1.fc4 100% | 101.6 MiB/s | 312.0 KiB | 00m00s [12/80] python3-cycler-0:0.11.0-22.fc45 100% | 7.2 MiB/s | 22.0 KiB | 00m00s [13/80] python3-dateutil-1:2.9.0.post0- 100% | 112.0 MiB/s | 344.1 KiB | 00m00s [14/80] python3-fonttools-0:4.67.0-1.fc 100% | 243.6 MiB/s | 3.4 MiB | 00m00s [15/80] python3-kiwisolver-0:1.5.1-1.fc 100% | 17.3 MiB/s | 70.7 KiB | 00m00s [16/80] python3-matplotlib-data-fonts-0 100% | 251.5 MiB/s | 2.5 MiB | 00m00s [17/80] python3-numpy-1:2.5.4-2.fc46.x8 100% | 302.5 MiB/s | 8.5 MiB | 00m00s [18/80] python3-packaging-0:26.3-1.fc46 100% | 95.6 MiB/s | 293.6 KiB | 00m00s [19/80] python3-pyparsing-0:3.1.2-19.fc 100% | 70.0 MiB/s | 286.9 KiB | 00m00s [20/80] python3-iniconfig-0:2.3.0-5.fc4 100% | 8.4 MiB/s | 25.8 KiB | 00m00s [21/80] python3-pluggy-0:1.7.0-1.fc46.n 100% | 24.4 MiB/s | 75.0 KiB | 00m00s [22/80] python3-pygments-0:2.20.0-5.fc4 100% | 147.7 MiB/s | 2.7 MiB | 00m00s [23/80] python3-libsbml-0:5.21.2-100.fc 100% | 20.6 MiB/s | 4.8 MiB | 00m00s [24/80] poco-foundation-0:1.14.1-3.fc44 100% | 97.5 MiB/s | 699.2 KiB | 00m00s [25/80] llvm14-libs-0:14.0.5-15.fc45.x8 100% | 230.7 MiB/s | 23.1 MiB | 00m00s [26/80] poco-net-0:1.14.1-3.fc44.x86_64 100% | 18.2 MiB/s | 465.9 KiB | 00m00s [27/80] python3-roadrunner-0:2.10.0-11. 100% | 8.1 MiB/s | 2.4 MiB | 00m00s [28/80] minizip-ng-compat-0:4.1.0-5.fc4 100% | 20.4 MiB/s | 62.8 KiB | 00m00s [29/80] python3-libs-0:3.15.0-1.fc46.x8 100% | 340.4 MiB/s | 11.2 MiB | 00m00s [30/80] fonts-filesystem-1:5.0.0-4.fc45 100% | 2.8 MiB/s | 8.7 KiB | 00m00s [31/80] harfbuzz-0:14.5.1-1.fc46.x86_64 100% | 236.6 MiB/s | 1.2 MiB | 00m00s [32/80] libpng-2:1.6.58-2.fc45.x86_64 100% | 63.1 MiB/s | 129.1 KiB | 00m00s [33/80] fribidi-0:1.0.17-2.fc46.x86_64 100% | 33.2 MiB/s | 101.8 KiB | 00m00s [34/80] tzdata-0:2026e-1.fc46.noarch 100% | 174.2 MiB/s | 713.6 KiB | 00m00s [35/80] flexiblas-netlib-0:3.5.0-4.fc46 100% | 299.0 MiB/s | 4.5 MiB | 00m00s [36/80] python3-numpy-f2py-1:2.5.4-2.fc 100% | 126.0 MiB/s | 516.0 KiB | 00m00s [37/80] libedit-0:3.1-60.20260512cvs.fc 100% | 35.8 MiB/s | 110.0 KiB | 00m00s [38/80] utf8proc-0:2.11.3-3.fc45.x86_64 100% | 27.0 MiB/s | 83.1 KiB | 00m00s [39/80] expat-0:2.9.0-1.fc46.x86_64 100% | 66.5 MiB/s | 136.2 KiB | 00m00s [40/80] mpdecimal-0:4.0.1-4.fc45.x86_64 100% | 48.1 MiB/s | 98.5 KiB | 00m00s [41/80] python-pip-wheel-0:26.2.1-1.fc4 100% | 198.8 MiB/s | 1.2 MiB | 00m00s [42/80] lapack-0:3.12.0-12.fc45.x86_64 100% | 347.6 MiB/s | 12.5 MiB | 00m00s [43/80] glib2-0:2.90.1-1.fc46.x86_64 100% | 267.4 MiB/s | 3.2 MiB | 00m00s [44/80] graphite2-0:1.3.14-22.fc45.x86_ 100% | 46.3 MiB/s | 94.8 KiB | 00m00s [45/80] flexiblas-0:3.5.0-4.fc46.x86_64 100% | 11.0 MiB/s | 22.6 KiB | 00m00s [46/80] flexiblas-openblas-openmp-0:3.5 100% | 8.0 MiB/s | 16.5 KiB | 00m00s [47/80] libgfortran-0:16.2.1-2.fc46.1.x 100% | 192.8 MiB/s | 987.1 KiB | 00m00s [48/80] libquadmath-0:16.2.1-2.fc46.1.x 100% | 67.6 MiB/s | 207.7 KiB | 00m00s [49/80] blas-0:3.12.0-12.fc45.x86_64 100% | 112.2 MiB/s | 689.6 KiB | 00m00s [50/80] openblas-openmp-0:0.3.34-1.fc45 100% | 288.8 MiB/s | 5.5 MiB | 00m00s [51/80] python3-0:3.15.0-1.fc46.x86_64 100% | 13.4 MiB/s | 27.5 KiB | 00m00s [52/80] rr-libstruct-0:2.9.2-0.4.git7ff 100% | 553.4 KiB/s | 102.4 KiB | 00m00s [53/80] python3-cairo-0:1.28.0-8.fc45.x 100% | 42.2 MiB/s | 129.7 KiB | 00m00s [54/80] fontconfig-0:2.18.3-3.fc46.x86_ 100% | 93.7 MiB/s | 383.6 KiB | 00m00s [55/80] cairo-0:1.18.6-1.fc46.x86_64 100% | 92.5 MiB/s | 757.6 KiB | 00m00s [56/80] libX11-0:1.8.13-3.fc46.x86_64 100% | 164.8 MiB/s | 674.9 KiB | 00m00s [57/80] libXext-0:1.3.6-6.fc45.x86_64 100% | 7.8 MiB/s | 40.1 KiB | 00m00s [58/80] libXrender-0:0.9.12-5.fc45.x86_ 100% | 13.6 MiB/s | 27.8 KiB | 00m00s [59/80] libxcb-0:1.17.0-8.fc45.x86_64 100% | 116.2 MiB/s | 237.9 KiB | 00m00s [60/80] lzo-0:2.10-17.fc45.x86_64 100% | 23.0 MiB/s | 70.6 KiB | 00m00s [61/80] pixman-0:0.46.2-4.fc45.x86_64 100% | 96.6 MiB/s | 296.7 KiB | 00m00s [62/80] default-fonts-core-sans-0:4.3-4 100% | 9.4 MiB/s | 28.8 KiB | 00m00s [63/80] xml-common-0:0.6.3-70.fc46.noar 100% | 15.2 MiB/s | 31.0 KiB | 00m00s [64/80] libX11-common-0:1.8.13-3.fc46.n 100% | 85.6 MiB/s | 175.2 KiB | 00m00s [65/80] libXau-0:1.0.12-5.fc45.x86_64 100% | 16.4 MiB/s | 33.5 KiB | 00m00s [66/80] google-noto-sans-vf-fonts-0:202 100% | 149.9 MiB/s | 614.1 KiB | 00m00s [67/80] google-noto-fonts-common-0:2026 100% | 5.5 MiB/s | 16.8 KiB | 00m00s [68/80] lcms2-0:2.16-8.fc45.x86_64 100% | 46.5 MiB/s | 190.3 KiB | 00m00s [69/80] python3-pillow-0:13.0.0-1.fc46. 100% | 151.8 MiB/s | 1.1 MiB | 00m00s [70/80] libimagequant-0:4.1.0-4.fc46.x8 100% | 102.6 MiB/s | 315.3 KiB | 00m00s [71/80] libjpeg-turbo-0:3.1.4.1-2.fc45. 100% | 79.0 MiB/s | 242.6 KiB | 00m00s [72/80] libtiff-0:4.7.2-3.fc46.x86_64 100% | 75.9 MiB/s | 233.3 KiB | 00m00s [73/80] libwebp-0:1.6.0-4.fc45.x86_64 100% | 107.1 MiB/s | 328.9 KiB | 00m00s [74/80] openjpeg-0:2.5.4-4.fc45.x86_64 100% | 64.0 MiB/s | 196.7 KiB | 00m00s [75/80] python3-olefile-0:0.47-15.fc45. 100% | 24.4 MiB/s | 75.0 KiB | 00m00s [76/80] jbigkit-libs-0:2.1-34.fc45.x86_ 100% | 26.4 MiB/s | 54.1 KiB | 00m00s [77/80] liblerc-0:4.2.0-1.fc45.x86_64 100% | 112.4 MiB/s | 230.1 KiB | 00m00s [78/80] openblas-0:0.3.34-1.fc45.x86_64 100% | 23.5 MiB/s | 48.2 KiB | 00m00s [79/80] python3-rpm-generators-0:14-35. 100% | 14.1 MiB/s | 28.8 KiB | 00m00s [80/80] libsbml-0:5.21.2-100.fc46.biofe 100% | 7.0 MiB/s | 2.6 MiB | 00m00s -------------------------------------------------------------------------------- [80/80] Total 100% | 166.1 MiB/s | 115.8 MiB | 00m01s Running transaction [ 1/82] Verify package files 100% | 206.0 B/s | 80.0 B | 00m00s [ 2/82] Prepare transaction 100% | 808.0 B/s | 80.0 B | 00m00s [ 3/82] Installing libgfortran-0:16.2.1 100% | 378.0 MiB/s | 3.4 MiB | 00m00s [ 4/82] Installing fonts-filesystem-1:5 100% | 0.0 B/s | 788.0 B | 00m00s [ 5/82] Installing python-rpm-macros-0: 100% | 0.0 B/s | 28.9 KiB | 00m00s [ 6/82] Installing python3-rpm-macros-0 100% | 6.6 MiB/s | 6.8 KiB | 00m00s [ 7/82] Installing blas-0:3.12.0-12.fc4 100% | 211.6 MiB/s | 1.5 MiB | 00m00s [ 8/82] Installing libwebp-0:1.6.0-4.fc 100% | 316.5 MiB/s | 972.2 KiB | 00m00s [ 9/82] Installing libjpeg-turbo-0:3.1. 100% | 160.9 MiB/s | 823.6 KiB | 00m00s [10/82] Installing tzdata-0:2026e-1.fc4 100% | 58.6 MiB/s | 1.5 MiB | 00m00s [11/82] Installing libpng-2:1.6.58-2.fc 100% | 248.9 MiB/s | 254.9 KiB | 00m00s [12/82] Installing minizip-ng-compat-0: 100% | 143.5 MiB/s | 146.9 KiB | 00m00s [13/82] Installing libsbml-0:5.21.2-100 100% | 249.1 MiB/s | 10.5 MiB | 00m00s [14/82] Installing lapack-0:3.12.0-12.f 100% | 126.7 MiB/s | 17.6 MiB | 00m00s [15/82] Installing rr-libstruct-0:2.9.2 100% | 249.8 MiB/s | 255.8 KiB | 00m00s [16/82] Installing pyproject-rpm-macros 100% | 167.4 MiB/s | 171.5 KiB | 00m00s [17/82] Installing dejavu-sans-fonts-0: 100% | 459.1 MiB/s | 5.5 MiB | 00m00s [18/82] Installing openblas-0:0.3.34-1. 100% | 0.0 B/s | 139.9 KiB | 00m00s [19/82] Installing openblas-openmp-0:0. 100% | 678.3 MiB/s | 44.8 MiB | 00m00s [20/82] Installing liblerc-0:4.2.0-1.fc 100% | 323.5 MiB/s | 662.6 KiB | 00m00s [21/82] Installing jbigkit-libs-0:2.1-3 100% | 116.4 MiB/s | 119.2 KiB | 00m00s [22/82] Installing libtiff-0:4.7.2-3.fc 100% | 315.8 MiB/s | 646.8 KiB | 00m00s [23/82] Installing openjpeg-0:2.5.4-4.f 100% | 227.6 MiB/s | 466.2 KiB | 00m00s [24/82] Installing libimagequant-0:4.1. 100% | 336.5 MiB/s | 689.1 KiB | 00m00s [25/82] Installing lcms2-0:2.16-8.fc45. 100% | 218.5 MiB/s | 447.4 KiB | 00m00s [26/82] Installing google-noto-fonts-co 100% | 0.0 B/s | 18.5 KiB | 00m00s [27/82] Installing google-noto-sans-vf- 100% | 347.8 MiB/s | 1.4 MiB | 00m00s [28/82] Installing default-fonts-core-s 100% | 17.8 MiB/s | 18.2 KiB | 00m00s [29/82] Installing libXau-0:1.0.12-5.fc 100% | 72.6 MiB/s | 74.3 KiB | 00m00s [30/82] Installing libxcb-0:1.17.0-8.fc 100% | 270.3 MiB/s | 1.1 MiB | 00m00s [31/82] Installing libX11-common-0:1.8. 100% | 197.6 MiB/s | 1.2 MiB | 00m00s [32/82] Installing libX11-0:1.8.13-3.fc 100% | 337.0 MiB/s | 1.3 MiB | 00m00s [33/82] Installing libXext-0:1.3.6-6.fc 100% | 0.0 B/s | 91.1 KiB | 00m00s [34/82] Installing libXrender-0:0.9.12- 100% | 10.0 MiB/s | 51.2 KiB | 00m00s [35/82] Installing xml-common-0:0.6.3-7 100% | 79.2 MiB/s | 81.1 KiB | 00m00s [36/82] Installing pixman-0:0.46.2-4.fc 100% | 351.3 MiB/s | 719.4 KiB | 00m00s [37/82] Installing lzo-0:2.10-17.fc45.x 100% | 176.2 MiB/s | 180.4 KiB | 00m00s [38/82] Installing libquadmath-0:16.2.1 100% | 315.6 MiB/s | 323.2 KiB | 00m00s [39/82] Installing flexiblas-netlib-0:3 100% | 307.6 MiB/s | 16.3 MiB | 00m00s [40/82] Installing flexiblas-0:3.5.0-4. 100% | 0.0 B/s | 39.2 KiB | 00m00s [41/82] Installing flexiblas-openblas-o 100% | 0.0 B/s | 40.0 KiB | 00m00s [42/82] Installing graphite2-0:1.3.14-2 100% | 11.1 MiB/s | 193.5 KiB | 00m00s [43/82] Installing glib2-0:2.90.1-1.fc4 100% | 307.5 MiB/s | 15.7 MiB | 00m00s [44/82] Installing freetype-0:2.15.0-1. 100% | 308.8 MiB/s | 948.5 KiB | 00m00s [45/82] Installing harfbuzz-0:14.5.1-1. 100% | 376.5 MiB/s | 3.0 MiB | 00m00s [46/82] Installing fontconfig-0:2.18.3- 100% | 1.0 MiB/s | 1.1 MiB | 00m01s [47/82] Installing cairo-0:1.18.6-1.fc4 100% | 366.4 MiB/s | 1.8 MiB | 00m00s [48/82] Installing python-pip-wheel-0:2 100% | 634.1 MiB/s | 1.3 MiB | 00m00s [49/82] Installing mpdecimal-0:4.0.1-4. 100% | 217.5 MiB/s | 222.7 KiB | 00m00s [50/82] Installing expat-0:2.9.0-1.fc46 100% | 15.6 MiB/s | 351.7 KiB | 00m00s [51/82] Installing python3-libs-0:3.15. 100% | 380.4 MiB/s | 48.7 MiB | 00m00s [52/82] Installing python3-0:3.15.0-1.f 100% | 1.5 MiB/s | 30.4 KiB | 00m00s [53/82] Installing python3-numpy-1:2.5. 100% | 374.2 MiB/s | 43.4 MiB | 00m00s [54/82] Installing python3-numpy-f2py-1 100% | 87.8 MiB/s | 2.2 MiB | 00m00s [55/82] Installing python3-packaging-0: 100% | 326.5 MiB/s | 1.3 MiB | 00m00s [56/82] Installing python3-rpm-generato 100% | 0.0 B/s | 83.1 KiB | 00m00s [57/82] Installing python3-contourpy-0: 100% | 306.3 MiB/s | 941.0 KiB | 00m00s [58/82] Installing python3-cycler-0:0.1 100% | 39.6 MiB/s | 40.6 KiB | 00m00s [59/82] Installing python3-dateutil-1:2 100% | 174.0 MiB/s | 890.8 KiB | 00m00s [60/82] Installing python3-fonttools-0: 100% | 398.1 MiB/s | 20.3 MiB | 00m00s [61/82] Installing python3-kiwisolver-0 100% | 158.2 MiB/s | 162.0 KiB | 00m00s [62/82] Installing python3-pyparsing-0: 100% | 346.1 MiB/s | 1.0 MiB | 00m00s [63/82] Installing python3-iniconfig-0: 100% | 52.7 MiB/s | 54.0 KiB | 00m00s [64/82] Installing python3-pluggy-0:1.7 100% | 62.3 MiB/s | 255.2 KiB | 00m00s [65/82] Installing python3-pygments-0:2 100% | 221.8 MiB/s | 11.5 MiB | 00m00s [66/82] Installing python3-cairo-0:1.28 100% | 251.2 MiB/s | 514.4 KiB | 00m00s [67/82] Installing python3-olefile-0:0. 100% | 342.5 MiB/s | 350.7 KiB | 00m00s [68/82] Installing utf8proc-0:2.11.3-3. 100% | 366.1 MiB/s | 374.9 KiB | 00m00s [69/82] Installing poco-foundation-0:1. 100% | 452.6 MiB/s | 2.3 MiB | 00m00s [70/82] Installing poco-net-0:1.14.1-3. 100% | 484.3 MiB/s | 1.5 MiB | 00m00s [71/82] Installing libedit-0:3.1-60.202 100% | 244.1 MiB/s | 250.0 KiB | 00m00s [72/82] Installing llvm14-libs-0:14.0.5 100% | 492.2 MiB/s | 96.0 MiB | 00m00s [73/82] Installing fribidi-0:1.0.17-2.f 100% | 22.8 MiB/s | 397.2 KiB | 00m00s [74/82] Installing libraqm-0:0.10.1-5.f 100% | 32.8 MiB/s | 33.6 KiB | 00m00s [75/82] Installing python3-pillow-0:13. 100% | 356.3 MiB/s | 4.6 MiB | 00m00s [76/82] Installing python3-matplotlib-d 100% | 447.0 MiB/s | 8.5 MiB | 00m00s [77/82] Installing libqhull_r-1:8.0.2-1 100% | 119.2 MiB/s | 488.1 KiB | 00m00s [78/82] Installing python3-matplotlib-0 100% | 470.0 MiB/s | 34.8 MiB | 00m00s [79/82] Installing python3-roadrunner-0 100% | 447.5 MiB/s | 12.1 MiB | 00m00s [80/82] Installing python3-pytest-0:9.1 100% | 387.9 MiB/s | 24.4 MiB | 00m00s [81/82] Installing python3-devel-0:3.15 100% | 100.2 MiB/s | 2.5 MiB | 00m00s [82/82] Installing python3-libsbml-0:5. 100% | 239.7 MiB/s | 34.5 MiB | 00m00s Warning: skipped OpenPGP checks for 4 packages from repository: copr_base Complete! Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1792713600 Wrote: /builddir/build/SRPMS/python-sbmlutils-0.17.0-1.fc46.src.rpm Updating and loading repositories: fedora 100% | 187.0 KiB/s | 22.4 KiB | 00m00s Additional repo copr_mhough_neurofedor 100% | 15.0 KiB/s | 1.5 KiB | 00m00s Copr repository 100% | 15.2 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Nothing to do. Package "pyproject-rpm-macros-1.24.0-1.fc46.noarch" is already installed. Package "python3-devel-3.15.0-1.fc46.x86_64" is already installed. Package "python3-libsbml-5.21.2-100.fc46.biofedora.x86_64" is already installed. Package "python3-matplotlib-3.11.1-2.fc45.x86_64" is already installed. Package "python3-pytest-9.1.1-1.fc45.noarch" is already installed. Package "python3-roadrunner-2.10.0-11.fc46.x86_64" is already installed. Finish: build setup for python-sbmlutils-0.17.0-1.fc46.src.rpm Start: rpmbuild python-sbmlutils-0.17.0-1.fc46.src.rpm Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1792713600 Executing(mkbuilddir): /bin/sh -e /var/tmp/rpm-tmp.h4A5Vt Creating(rpmbuild.env): /builddir/build/BUILD/python-sbmlutils-0.17.0-build/rpmbuild.env RPM_SOURCE_DIR="/builddir/build/SOURCES" RPM_BUILD_DIR="/builddir/build/BUILD/python-sbmlutils-0.17.0-build" RPM_OPT_FLAGS="-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wno-complain-wrong-lang -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer" RPM_LD_FLAGS="-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes " RPM_ARCH="x86_64" RPM_OS="linux" RPM_BUILD_NCPUS="4" RPM_SPECPARTS_DIR="/builddir/build/BUILD/python-sbmlutils-0.17.0-build/SPECPARTS" export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS RPM_SPECPARTS_DIR RPM_LD_FLAGS RPM_DOC_DIR="/usr/share/doc" export RPM_DOC_DIR RPM_PACKAGE_NAME="python-sbmlutils" RPM_PACKAGE_VERSION="0.17.0" RPM_PACKAGE_RELEASE="1.fc46" export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE LANG=C.UTF-8 export LANG unset CDPATH DISPLAY ||: unset DEBUGINFOD_URLS ||: unset RPM_CONFIG_DIR ||: RPM_BUILD_ROOT="/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT" export RPM_BUILD_ROOT PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/lib64/pkgconfig:/usr/share/pkgconfig" export PKG_CONFIG_PATH CONFIG_SITE=${CONFIG_SITE:-NONE} export CONFIG_SITE Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.TOflUF + umask 022 + cd /builddir/build/BUILD/python-sbmlutils-0.17.0-build + cd /builddir/build/BUILD/python-sbmlutils-0.17.0-build + rm -rf sbmlutils-0.17.0 + /usr/bin/rpmuncompress -x /builddir/build/SOURCES/sbmlutils-0.17.0.tar.gz + STATUS=0 + '[' 0 -ne 0 ']' + cd sbmlutils-0.17.0 + /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w . + grep -qP '^\t"python-libsbml>=5\.21\.2",$' pyproject.toml + sed -i '/^\t"python-libsbml>=5\.21\.2",$/d' pyproject.toml + for d in 'pint>=0.25.3:pint>=0.25' 'xmltodict>=1.0.2:xmltodict>=0.14' 'certifi>=2026.10.19:certifi>=2025' + old='pint>=0.25.3' + new='pint>=0.25' + grep -qP '^\t"pint>=0.25.3",$' pyproject.toml + sed -i 's/^\t"pint>=0.25.3",$/\t"pint>=0.25",/' pyproject.toml + for d in 'pint>=0.25.3:pint>=0.25' 'xmltodict>=1.0.2:xmltodict>=0.14' 'certifi>=2026.10.19:certifi>=2025' + old='xmltodict>=1.0.2' + new='xmltodict>=0.14' + grep -qP '^\t"xmltodict>=1.0.2",$' pyproject.toml + sed -i 's/^\t"xmltodict>=1.0.2",$/\t"xmltodict>=0.14",/' pyproject.toml + for d in 'pint>=0.25.3:pint>=0.25' 'xmltodict>=1.0.2:xmltodict>=0.14' 'certifi>=2026.10.19:certifi>=2025' + old='certifi>=2026.10.19' + new='certifi>=2025' + grep -qP '^\t"certifi>=2026.10.19",$' pyproject.toml + sed -i 's/^\t"certifi>=2026.10.19",$/\t"certifi>=2025",/' pyproject.toml + RPM_EC=0 ++ jobs -p + exit 0 Executing(%generate_buildrequires): /bin/sh -e /var/tmp/rpm-tmp.rFziZZ + umask 022 + cd /builddir/build/BUILD/python-sbmlutils-0.17.0-build + cd sbmlutils-0.17.0 + echo pyproject-rpm-macros + echo python3-devel + echo 'python3dist(packaging)' + echo 'python3dist(pip) >= 19' + '[' -f pyproject.toml ']' + echo '(python3dist(tomli) if python3-devel < 3.11)' + rm -rfv '*.dist-info/' + '[' -f /usr/bin/python3 ']' + mkdir -p /builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir + echo -n + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + VALAFLAGS=-g + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes --cap-lints=warn' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 ' + LT_SYS_LIBRARY_PATH=/usr/lib64: + CC=gcc + CXX=g++ + TMPDIR=/builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir + RPM_TOXENV=py315 + FEDORA=46 + HOSTNAME=rpmbuild + /usr/bin/python3 -Bs /usr/lib/rpm/redhat/pyproject_buildrequires.py --generate-extras --python3_pkgversion 3 --wheeldir /builddir/build/BUILD/python-sbmlutils-0.17.0-build/pyproject-wheeldir --output /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-dep-overrides Handling hatchling from build-system.requires Requirement not satisfied: hatchling Exiting dependency generation pass: build backend + cat /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-buildrequires + rm -rfv '*.dist-info/' + RPM_EC=0 ++ jobs -p + exit 0 Wrote: /builddir/build/SRPMS/python-sbmlutils-0.17.0-1.fc46.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: fedora 100% | 90.1 KiB/s | 22.4 KiB | 00m00s Additional repo copr_mhough_neurofedor 100% | 6.6 KiB/s | 1.5 KiB | 00m00s Copr repository 100% | 6.7 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc46.noarch" is already installed. Package "python3-devel-3.15.0-1.fc46.x86_64" is already installed. Package "python3-libsbml-5.21.2-100.fc46.biofedora.x86_64" is already installed. Package "python3-matplotlib-3.11.1-2.fc45.x86_64" is already installed. Package "python3-pytest-9.1.1-1.fc45.noarch" is already installed. Package "python3-roadrunner-2.10.0-11.fc46.x86_64" is already installed. Package "python3-packaging-26.3-1.fc46.noarch" is already installed. Package Arch Version Repository Size Installing: python3-hatchling noarch 0:1.32.4-1.fc46 fedora 705.0 KiB python3-pip noarch 0:26.2.1-1.fc46 fedora 12.3 MiB Installing dependencies: python3-pathspec noarch 0:1.1.1-4.fc45 fedora 421.6 KiB python3-tomlkit noarch 0:0.13.2-10.fc46 fedora 503.4 KiB python3-trove-classifiers noarch 0:2026.9.21.13-1.fc46 fedora 112.7 KiB Transaction Summary: Installing: 5 packages Total size of inbound packages is 3 MiB. Need to download 3 MiB. After this operation, 14 MiB extra will be used (install 14 MiB, remove 0 B). [1/5] python3-hatchling-0:1.32.4-1.fc46 100% | 46.3 MiB/s | 237.2 KiB | 00m00s [2/5] python3-pathspec-0:1.1.1-4.fc45.n 100% | 21.9 MiB/s | 112.0 KiB | 00m00s [3/5] python3-tomlkit-0:0.13.2-10.fc46. 100% | 30.9 MiB/s | 126.8 KiB | 00m00s [4/5] python3-trove-classifiers-0:2026. 100% | 16.6 MiB/s | 34.1 KiB | 00m00s [5/5] python3-pip-0:26.2.1-1.fc46.noarc 100% | 232.3 MiB/s | 2.8 MiB | 00m00s -------------------------------------------------------------------------------- [5/5] Total 100% | 149.3 MiB/s | 3.3 MiB | 00m00s Running transaction [1/7] Verify package files 100% | 454.0 B/s | 5.0 B | 00m00s [2/7] Prepare transaction 100% | 200.0 B/s | 5.0 B | 00m00s [3/7] Installing python3-trove-classifi 100% | 6.7 MiB/s | 116.4 KiB | 00m00s [4/7] Installing python3-tomlkit-0:0.13 100% | 250.2 MiB/s | 512.5 KiB | 00m00s [5/7] Installing python3-pathspec-0:1.1 100% | 144.5 MiB/s | 443.9 KiB | 00m00s [6/7] Installing python3-hatchling-0:1. 100% | 30.7 MiB/s | 754.2 KiB | 00m00s [7/7] Installing python3-pip-0:26.2.1-1 100% | 165.0 MiB/s | 12.5 MiB | 00m00s Complete! Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1792713600 Executing(%generate_buildrequires): /bin/sh -e /var/tmp/rpm-tmp.OWqfA8 + umask 022 + cd /builddir/build/BUILD/python-sbmlutils-0.17.0-build + cd sbmlutils-0.17.0 + echo pyproject-rpm-macros + echo python3-devel + echo 'python3dist(packaging)' + echo 'python3dist(pip) >= 19' + '[' -f pyproject.toml ']' + echo '(python3dist(tomli) if python3-devel < 3.11)' + rm -rfv '*.dist-info/' + '[' -f /usr/bin/python3 ']' + mkdir -p /builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir + echo -n + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + VALAFLAGS=-g + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes --cap-lints=warn' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 ' + LT_SYS_LIBRARY_PATH=/usr/lib64: + CC=gcc + CXX=g++ + TMPDIR=/builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir + RPM_TOXENV=py315 + FEDORA=46 + HOSTNAME=rpmbuild + /usr/bin/python3 -Bs /usr/lib/rpm/redhat/pyproject_buildrequires.py --generate-extras --python3_pkgversion 3 --wheeldir /builddir/build/BUILD/python-sbmlutils-0.17.0-build/pyproject-wheeldir --output /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-dep-overrides Handling hatchling from build-system.requires Requirement satisfied: hatchling (installed: hatchling 1.32.4) Handling antimony!=3.2.0; sys_platform == 'win32' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: antimony!=3.2.0; sys_platform == 'win32' Handling antimony>=3.1.3 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: antimony>=3.1.3 Handling certifi>=2025 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: certifi>=2025 Handling jinja2>=3.1.6 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: jinja2>=3.1.6 Handling lxml>=6.1.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: lxml>=6.1.0 Handling markdown-it-py>=3.0.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: markdown-it-py>=3.0.0 Handling numpy>=2.2.2 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: numpy>=2.2.2 (installed: numpy 2.5.4) Handling openpyxl>=3.1.5 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: openpyxl>=3.1.5 Handling pandas>=2.2.2 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: pandas>=2.2.2 Handling pint>=0.25 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: pint>=0.25 Handling pymetadata>=0.8.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: pymetadata>=0.8.0 Handling requests>=2.32.4 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: requests>=2.32.4 Handling rich>=13.0.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: rich>=13.0.0 Handling sbmlode>=0.2.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: sbmlode>=0.2.0 Handling xmltodict>=0.14 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: xmltodict>=0.14 Handling cobra>=0.32.1; extra == 'cobra' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: cobra>=0.32.1; extra == 'cobra' Handling py4cytoscape>=1.13.0; extra == 'cytoscape' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: py4cytoscape>=1.13.0; extra == 'cytoscape' Handling bump-my-version>=1.5.1; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: bump-my-version>=1.5.1; extra == 'dev' Handling libroadrunner>=2.10.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: libroadrunner>=2.10.0; extra == 'dev' Handling matplotlib>=3.11.1; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: matplotlib>=3.11.1; extra == 'dev' Handling mkdocstrings-python>=2.0.8; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: mkdocstrings-python>=2.0.8; extra == 'dev' Handling pre-commit>=4.6.2; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pre-commit>=4.6.2; extra == 'dev' Handling py4cytoscape>=1.13.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: py4cytoscape>=1.13.0; extra == 'dev' Handling pytest-cov>=7.1.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pytest-cov>=7.1.0; extra == 'dev' Handling pytest-xdist>=3.8.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pytest-xdist>=3.8.0; extra == 'dev' Handling pytest>=9.1.1; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pytest>=9.1.1; extra == 'dev' Handling ruff>=0.16.6; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: ruff>=0.16.6; extra == 'dev' Handling tox>=4.61.2; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: tox>=4.61.2; extra == 'dev' Handling ty>=0.0.79; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: ty>=0.0.79; extra == 'dev' Handling zensical>=0.0.60; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: zensical>=0.0.60; extra == 'dev' Handling libroadrunner>=2.10.0; extra == 'examples' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: libroadrunner>=2.10.0; extra == 'examples' Handling matplotlib>=3.11.1; extra == 'examples' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: matplotlib>=3.11.1; extra == 'examples' + cat /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-buildrequires + rm -rfv sbmlutils-0.17.0.dist-info/ removed 'sbmlutils-0.17.0.dist-info/METADATA' removed directory 'sbmlutils-0.17.0.dist-info/' + RPM_EC=0 ++ jobs -p + exit 0 Wrote: /builddir/build/SRPMS/python-sbmlutils-0.17.0-1.fc46.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: fedora 100% | 166.2 KiB/s | 22.4 KiB | 00m00s Additional repo copr_mhough_neurofedor 100% | 13.3 KiB/s | 1.5 KiB | 00m00s Copr repository 100% | 12.9 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc46.noarch" is already installed. Package "python3-devel-3.15.0-1.fc46.x86_64" is already installed. Package "python3-libsbml-5.21.2-100.fc46.biofedora.x86_64" is already installed. Package "python3-matplotlib-3.11.1-2.fc45.x86_64" is already installed. Package "python3-pytest-9.1.1-1.fc45.noarch" is already installed. Package "python3-roadrunner-2.10.0-11.fc46.x86_64" is already installed. Package "python3-hatchling-1.32.4-1.fc46.noarch" is already installed. Package "python3-numpy-1:2.5.4-2.fc46.x86_64" is already installed. Package "python3-packaging-26.3-1.fc46.noarch" is already installed. Package "python3-pip-26.2.1-1.fc46.noarch" is already installed. Package Arch Version Repository Size Installing: python3-antimony x86_64 0:3.2.1-1.fc46 copr_base 2.1 MiB python3-certifi noarch 0:2026.01.04-3.fc45 fedora 7.5 KiB python3-jinja2 noarch 0:3.1.6-11.fc46 fedora 3.3 MiB python3-lxml x86_64 0:6.1.2-1.fc46 fedora 5.8 MiB python3-markdown-it-py noarch 0:4.2.0-2.fc45 fedora 577.0 KiB python3-openpyxl noarch 0:3.1.5-7.fc45 fedora 1.9 MiB python3-pandas x86_64 0:3.0.6-1.fc46 fedora 40.2 MiB python3-pint noarch 0:0.26.1-1.fc46 fedora 3.8 MiB python3-pymetadata noarch 0:0.8.2-1.fc46 copr_base 2.9 MiB python3-requests noarch 0:2.34.2-2.fc45 fedora 679.2 KiB python3-rich noarch 0:15.0.0-4.fc45 fedora 3.5 MiB python3-sbmlode noarch 0:0.3.1-1.fc46 copr_base 905.1 KiB python3-xmltodict noarch 0:0.14.2-7.fc45 fedora 56.1 KiB Installing dependencies: libsbmlnetwork x86_64 0:0.5.12-2.fc46 copr_base 3.5 MiB libxslt x86_64 0:1.1.43-10.fc46 fedora 471.8 KiB python3-Bottleneck x86_64 0:1.6.0-5.fc45 fedora 574.6 KiB python3-annotated-types noarch 0:0.8.0-1.fc45 fedora 83.8 KiB python3-charset-normalizer noarch 0:3.5.2-1.fc46 fedora 478.1 KiB python3-et_xmlfile noarch 0:2.0.0-10.fc45 fedora 100.7 KiB python3-flexcache noarch 0:0.3-15.fc45 fedora 58.0 KiB python3-flexparser noarch 0:0.4-13.fc45 fedora 271.0 KiB python3-idna noarch 0:3.19-1.fc46 fedora 510.6 KiB python3-markupsafe x86_64 0:3.0.2-10.fc45 fedora 62.8 KiB python3-mdurl noarch 0:0.1.2-16.fc45 fedora 44.3 KiB python3-numexpr x86_64 0:2.14.1-4.fc45 fedora 861.3 KiB python3-platformdirs noarch 0:4.13.3-1.fc46 fedora 360.4 KiB python3-pydantic noarch 0:2.14.1-1.fc46 fedora 5.4 MiB python3-pydantic-core x86_64 0:2.50.1-1.fc46 fedora 5.7 MiB python3-typing-extensions noarch 0:4.16.0-4.fc46 fedora 554.7 KiB python3-typing-inspection noarch 0:0.4.4-1.fc46 fedora 93.9 KiB python3-urllib3 noarch 0:2.8.0-3.fc46 fedora 1.2 MiB Transaction Summary: Installing: 31 packages Total size of inbound packages is 19 MiB. Need to download 19 MiB. After this operation, 86 MiB extra will be used (install 86 MiB, remove 0 B). [ 1/31] python3-certifi-0:2026.01.04-3. 100% | 4.9 MiB/s | 15.1 KiB | 00m00s [ 2/31] python3-markdown-it-py-0:4.2.0- 100% | 41.6 MiB/s | 213.0 KiB | 00m00s [ 3/31] python3-jinja2-0:3.1.6-11.fc46. 100% | 52.3 MiB/s | 642.8 KiB | 00m00s [ 4/31] python3-lxml-0:6.1.2-1.fc46.x86 100% | 84.0 MiB/s | 1.7 MiB | 00m00s [ 5/31] python3-pandas-0:3.0.6-1.fc46.x 100% | 280.4 MiB/s | 7.6 MiB | 00m00s [ 6/31] python3-requests-0:2.34.2-2.fc4 100% | 30.6 MiB/s | 188.0 KiB | 00m00s [ 7/31] python3-rich-0:15.0.0-4.fc45.no 100% | 108.7 MiB/s | 667.7 KiB | 00m00s [ 8/31] python3-openpyxl-0:3.1.5-7.fc45 100% | 5.3 MiB/s | 615.0 KiB | 00m00s [ 9/31] python3-pint-0:0.26.1-1.fc46.no 100% | 7.3 MiB/s | 796.3 KiB | 00m00s [10/31] python3-xmltodict-0:0.14.2-7.fc 100% | 1.1 MiB/s | 26.5 KiB | 00m00s [11/31] python3-sbmlode-0:0.3.1-1.fc46. 100% | 1.2 MiB/s | 232.1 KiB | 00m00s [12/31] python3-markupsafe-0:3.0.2-10.f 100% | 10.4 MiB/s | 31.9 KiB | 00m00s [13/31] libxslt-0:1.1.43-10.fc46.x86_64 100% | 93.5 MiB/s | 191.6 KiB | 00m00s [14/31] python3-mdurl-0:0.1.2-16.fc45.n 100% | 10.2 MiB/s | 31.3 KiB | 00m00s [15/31] python3-et_xmlfile-0:2.0.0-10.f 100% | 874.6 KiB/s | 45.5 KiB | 00m00s [16/31] python3-Bottleneck-0:1.6.0-5.fc 100% | 58.9 MiB/s | 180.9 KiB | 00m00s [17/31] python3-numexpr-0:2.14.1-4.fc45 100% | 56.7 MiB/s | 232.4 KiB | 00m00s [18/31] python3-flexcache-0:0.3-15.fc45 100% | 8.8 MiB/s | 27.0 KiB | 00m00s [19/31] python3-flexparser-0:0.4-13.fc4 100% | 27.0 MiB/s | 55.3 KiB | 00m00s [20/31] python3-platformdirs-0:4.13.3-1 100% | 42.1 MiB/s | 86.2 KiB | 00m00s [21/31] python3-typing-extensions-0:4.1 100% | 22.3 MiB/s | 114.1 KiB | 00m00s [22/31] python3-charset-normalizer-0:3. 100% | 69.1 MiB/s | 141.5 KiB | 00m00s [23/31] python3-idna-0:3.19-1.fc46.noar 100% | 26.3 MiB/s | 107.7 KiB | 00m00s [24/31] python3-pymetadata-0:0.8.2-1.fc 100% | 1.8 MiB/s | 375.6 KiB | 00m00s [25/31] python3-urllib3-0:2.8.0-3.fc46. 100% | 61.0 MiB/s | 312.3 KiB | 00m00s [26/31] python3-pydantic-0:2.14.1-1.fc4 100% | 172.0 MiB/s | 1.0 MiB | 00m00s [27/31] python3-antimony-0:3.2.1-1.fc46 100% | 2.7 MiB/s | 634.1 KiB | 00m00s [28/31] python3-annotated-types-0:0.8.0 100% | 10.0 MiB/s | 30.6 KiB | 00m00s [29/31] python3-typing-inspection-0:0.4 100% | 11.0 MiB/s | 33.8 KiB | 00m00s [30/31] python3-pydantic-core-0:2.50.1- 100% | 60.9 MiB/s | 1.8 MiB | 00m00s [31/31] libsbmlnetwork-0:0.5.12-2.fc46. 100% | 1.7 MiB/s | 578.5 KiB | 00m00s -------------------------------------------------------------------------------- [31/31] Total 100% | 26.9 MiB/s | 18.6 MiB | 00m01s Running transaction [ 1/33] Verify package files 100% | 500.0 B/s | 31.0 B | 00m00s [ 2/33] Prepare transaction 100% | 688.0 B/s | 31.0 B | 00m00s [ 3/33] Installing python3-typing-exten 100% | 272.0 MiB/s | 557.0 KiB | 00m00s [ 4/33] Installing python3-idna-0:3.19- 100% | 29.8 MiB/s | 518.5 KiB | 00m00s [ 5/33] Installing python3-urllib3-0:2. 100% | 300.4 MiB/s | 1.2 MiB | 00m00s [ 6/33] Installing python3-flexcache-0: 100% | 60.1 MiB/s | 61.6 KiB | 00m00s [ 7/33] Installing python3-flexparser-0 100% | 268.1 MiB/s | 274.6 KiB | 00m00s [ 8/33] Installing python3-pydantic-cor 100% | 436.7 MiB/s | 5.7 MiB | 00m00s [ 9/33] Installing python3-typing-inspe 100% | 95.7 MiB/s | 98.0 KiB | 00m00s [10/33] Installing python3-annotated-ty 100% | 84.9 MiB/s | 86.9 KiB | 00m00s [11/33] Installing python3-pydantic-0:2 100% | 388.6 MiB/s | 5.4 MiB | 00m00s [12/33] Installing libsbmlnetwork-0:0.5 100% | 589.0 MiB/s | 3.5 MiB | 00m00s [13/33] Installing python3-charset-norm 100% | 28.0 MiB/s | 488.2 KiB | 00m00s [14/33] Installing python3-requests-0:2 100% | 225.3 MiB/s | 692.0 KiB | 00m00s [15/33] Installing python3-platformdirs 100% | 180.3 MiB/s | 369.3 KiB | 00m00s [16/33] Installing python3-numexpr-0:2. 100% | 284.2 MiB/s | 873.0 KiB | 00m00s [17/33] Installing python3-Bottleneck-0 100% | 194.4 MiB/s | 597.3 KiB | 00m00s [18/33] Installing python3-mdurl-0:0.1. 100% | 48.5 MiB/s | 49.7 KiB | 00m00s [19/33] Installing python3-markdown-it- 100% | 30.3 MiB/s | 621.1 KiB | 00m00s [20/33] Installing python3-rich-0:15.0. 100% | 352.4 MiB/s | 3.5 MiB | 00m00s [21/33] Installing libxslt-0:1.1.43-10. 100% | 27.3 MiB/s | 474.9 KiB | 00m00s [22/33] Installing python3-lxml-0:6.1.2 100% | 366.6 MiB/s | 5.9 MiB | 00m00s [23/33] Installing python3-et_xmlfile-0 100% | 103.3 MiB/s | 105.8 KiB | 00m00s [24/33] Installing python3-markupsafe-0 100% | 65.5 MiB/s | 67.1 KiB | 00m00s [25/33] Installing python3-jinja2-0:3.1 100% | 412.9 MiB/s | 3.3 MiB | 00m00s [26/33] Installing python3-certifi-0:20 100% | 11.0 MiB/s | 11.3 KiB | 00m00s [27/33] Installing python3-pymetadata-0 100% | 494.6 MiB/s | 3.0 MiB | 00m00s [28/33] Installing python3-sbmlode-0:0. 100% | 224.7 MiB/s | 920.5 KiB | 00m00s [29/33] Installing python3-openpyxl-0:3 100% | 143.4 MiB/s | 2.0 MiB | 00m00s [30/33] Installing python3-pandas-0:3.0 100% | 443.6 MiB/s | 40.4 MiB | 00m00s [31/33] Installing python3-pint-0:0.26. 100% | 141.9 MiB/s | 3.8 MiB | 00m00s [32/33] Installing python3-antimony-0:3 100% | 424.8 MiB/s | 2.1 MiB | 00m00s [33/33] Installing python3-xmltodict-0: 100% | 2.7 MiB/s | 58.6 KiB | 00m00s Warning: skipped OpenPGP checks for 4 packages from repository: copr_base Complete! Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1792713600 Executing(%generate_buildrequires): /bin/sh -e /var/tmp/rpm-tmp.vZzWrJ + umask 022 + cd /builddir/build/BUILD/python-sbmlutils-0.17.0-build + cd sbmlutils-0.17.0 + echo pyproject-rpm-macros + echo python3-devel + echo 'python3dist(packaging)' + echo 'python3dist(pip) >= 19' + '[' -f pyproject.toml ']' + echo '(python3dist(tomli) if python3-devel < 3.11)' + rm -rfv '*.dist-info/' + '[' -f /usr/bin/python3 ']' + mkdir -p /builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir + echo -n + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + VALAFLAGS=-g + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes --cap-lints=warn' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 ' + LT_SYS_LIBRARY_PATH=/usr/lib64: + CC=gcc + CXX=g++ + TMPDIR=/builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir + RPM_TOXENV=py315 + FEDORA=46 + HOSTNAME=rpmbuild + /usr/bin/python3 -Bs /usr/lib/rpm/redhat/pyproject_buildrequires.py --generate-extras --python3_pkgversion 3 --wheeldir /builddir/build/BUILD/python-sbmlutils-0.17.0-build/pyproject-wheeldir --output /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-dep-overrides Handling hatchling from build-system.requires Requirement satisfied: hatchling (installed: hatchling 1.32.4) Handling antimony!=3.2.0; sys_platform == 'win32' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: antimony!=3.2.0; sys_platform == 'win32' Handling antimony>=3.1.3 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: antimony>=3.1.3 Handling certifi>=2025 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: certifi>=2025 (installed: certifi 2026.1.4) Handling jinja2>=3.1.6 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: jinja2>=3.1.6 (installed: jinja2 3.1.6) Handling lxml>=6.1.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: lxml>=6.1.0 (installed: lxml 6.1.2) Handling markdown-it-py>=3.0.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: markdown-it-py>=3.0.0 (installed: markdown-it-py 4.2.0) Handling numpy>=2.2.2 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: numpy>=2.2.2 (installed: numpy 2.5.4) Handling openpyxl>=3.1.5 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: openpyxl>=3.1.5 (installed: openpyxl 3.1.5) Handling pandas>=2.2.2 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: pandas>=2.2.2 (installed: pandas 3.0.6) Handling pint>=0.25 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: pint>=0.25 (installed: pint 0.26.1) Handling pymetadata>=0.8.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: pymetadata>=0.8.0 (installed: pymetadata 0.8.2) Handling requests>=2.32.4 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: requests>=2.32.4 (installed: requests 2.34.2) Handling rich>=13.0.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: rich>=13.0.0 (installed: rich 15.0.0) Handling sbmlode>=0.2.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: sbmlode>=0.2.0 (installed: sbmlode 0.3.1) Handling xmltodict>=0.14 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: xmltodict>=0.14 (installed: xmltodict 0.14.2) Handling cobra>=0.32.1; extra == 'cobra' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: cobra>=0.32.1; extra == 'cobra' Handling py4cytoscape>=1.13.0; extra == 'cytoscape' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: py4cytoscape>=1.13.0; extra == 'cytoscape' Handling bump-my-version>=1.5.1; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: bump-my-version>=1.5.1; extra == 'dev' Handling libroadrunner>=2.10.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: libroadrunner>=2.10.0; extra == 'dev' Handling matplotlib>=3.11.1; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: matplotlib>=3.11.1; extra == 'dev' Handling mkdocstrings-python>=2.0.8; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: mkdocstrings-python>=2.0.8; extra == 'dev' Handling pre-commit>=4.6.2; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pre-commit>=4.6.2; extra == 'dev' Handling py4cytoscape>=1.13.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: py4cytoscape>=1.13.0; extra == 'dev' Handling pytest-cov>=7.1.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pytest-cov>=7.1.0; extra == 'dev' Handling pytest-xdist>=3.8.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pytest-xdist>=3.8.0; extra == 'dev' Handling pytest>=9.1.1; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pytest>=9.1.1; extra == 'dev' Handling ruff>=0.16.6; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: ruff>=0.16.6; extra == 'dev' Handling tox>=4.61.2; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: tox>=4.61.2; extra == 'dev' Handling ty>=0.0.79; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: ty>=0.0.79; extra == 'dev' Handling zensical>=0.0.60; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: zensical>=0.0.60; extra == 'dev' Handling libroadrunner>=2.10.0; extra == 'examples' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: libroadrunner>=2.10.0; extra == 'examples' Handling matplotlib>=3.11.1; extra == 'examples' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: matplotlib>=3.11.1; extra == 'examples' + cat /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-buildrequires + rm -rfv sbmlutils-0.17.0.dist-info/ removed 'sbmlutils-0.17.0.dist-info/METADATA' removed directory 'sbmlutils-0.17.0.dist-info/' + RPM_EC=0 ++ jobs -p + exit 0 Wrote: /builddir/build/SRPMS/python-sbmlutils-0.17.0-1.fc46.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: fedora 100% | 165.0 KiB/s | 22.4 KiB | 00m00s Additional repo copr_mhough_neurofedor 100% | 13.1 KiB/s | 1.5 KiB | 00m00s Copr repository 100% | 13.2 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Nothing to do. Package "pyproject-rpm-macros-1.24.0-1.fc46.noarch" is already installed. Package "python3-devel-3.15.0-1.fc46.x86_64" is already installed. Package "python3-libsbml-5.21.2-100.fc46.biofedora.x86_64" is already installed. Package "python3-matplotlib-3.11.1-2.fc45.x86_64" is already installed. Package "python3-pytest-9.1.1-1.fc45.noarch" is already installed. Package "python3-roadrunner-2.10.0-11.fc46.x86_64" is already installed. Package "python3-antimony-3.2.1-1.fc46.x86_64" is already installed. Package "python3-certifi-2026.01.04-3.fc45.noarch" is already installed. Package "python3-hatchling-1.32.4-1.fc46.noarch" is already installed. Package "python3-jinja2-3.1.6-11.fc46.noarch" is already installed. Package "python3-lxml-6.1.2-1.fc46.x86_64" is already installed. Package "python3-markdown-it-py-4.2.0-2.fc45.noarch" is already installed. Package "python3-numpy-1:2.5.4-2.fc46.x86_64" is already installed. Package "python3-openpyxl-3.1.5-7.fc45.noarch" is already installed. Package "python3-packaging-26.3-1.fc46.noarch" is already installed. Package "python3-pandas-3.0.6-1.fc46.x86_64" is already installed. Package "python3-pint-0.26.1-1.fc46.noarch" is already installed. Package "python3-pip-26.2.1-1.fc46.noarch" is already installed. Package "python3-pymetadata-0.8.2-1.fc46.noarch" is already installed. Package "python3-requests-2.34.2-2.fc45.noarch" is already installed. Package "python3-rich-15.0.0-4.fc45.noarch" is already installed. Package "python3-sbmlode-0.3.1-1.fc46.noarch" is already installed. Package "python3-xmltodict-0.14.2-7.fc45.noarch" is already installed. Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1792713600 Executing(%generate_buildrequires): /bin/sh -e /var/tmp/rpm-tmp.elfHmA + umask 022 + cd /builddir/build/BUILD/python-sbmlutils-0.17.0-build + cd sbmlutils-0.17.0 + echo pyproject-rpm-macros + echo python3-devel + echo 'python3dist(packaging)' + echo 'python3dist(pip) >= 19' + '[' -f pyproject.toml ']' + echo '(python3dist(tomli) if python3-devel < 3.11)' + rm -rfv '*.dist-info/' + '[' -f /usr/bin/python3 ']' + mkdir -p /builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir + echo -n + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + VALAFLAGS=-g + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes --cap-lints=warn' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 ' + LT_SYS_LIBRARY_PATH=/usr/lib64: + CC=gcc + CXX=g++ + TMPDIR=/builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir + RPM_TOXENV=py315 + FEDORA=46 + HOSTNAME=rpmbuild + /usr/bin/python3 -Bs /usr/lib/rpm/redhat/pyproject_buildrequires.py --generate-extras --python3_pkgversion 3 --wheeldir /builddir/build/BUILD/python-sbmlutils-0.17.0-build/pyproject-wheeldir --output /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-dep-overrides Handling hatchling from build-system.requires Requirement satisfied: hatchling (installed: hatchling 1.32.4) Handling antimony!=3.2.0; sys_platform == 'win32' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: antimony!=3.2.0; sys_platform == 'win32' Handling antimony>=3.1.3 from hook generated metadata: Requires-Dist (sbmlutils) Requirement not satisfied: antimony>=3.1.3 Handling certifi>=2025 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: certifi>=2025 (installed: certifi 2026.1.4) Handling jinja2>=3.1.6 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: jinja2>=3.1.6 (installed: jinja2 3.1.6) Handling lxml>=6.1.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: lxml>=6.1.0 (installed: lxml 6.1.2) Handling markdown-it-py>=3.0.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: markdown-it-py>=3.0.0 (installed: markdown-it-py 4.2.0) Handling numpy>=2.2.2 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: numpy>=2.2.2 (installed: numpy 2.5.4) Handling openpyxl>=3.1.5 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: openpyxl>=3.1.5 (installed: openpyxl 3.1.5) Handling pandas>=2.2.2 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: pandas>=2.2.2 (installed: pandas 3.0.6) Handling pint>=0.25 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: pint>=0.25 (installed: pint 0.26.1) Handling pymetadata>=0.8.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: pymetadata>=0.8.0 (installed: pymetadata 0.8.2) Handling requests>=2.32.4 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: requests>=2.32.4 (installed: requests 2.34.2) Handling rich>=13.0.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: rich>=13.0.0 (installed: rich 15.0.0) Handling sbmlode>=0.2.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: sbmlode>=0.2.0 (installed: sbmlode 0.3.1) Handling xmltodict>=0.14 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: xmltodict>=0.14 (installed: xmltodict 0.14.2) Handling cobra>=0.32.1; extra == 'cobra' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: cobra>=0.32.1; extra == 'cobra' Handling py4cytoscape>=1.13.0; extra == 'cytoscape' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: py4cytoscape>=1.13.0; extra == 'cytoscape' Handling bump-my-version>=1.5.1; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: bump-my-version>=1.5.1; extra == 'dev' Handling libroadrunner>=2.10.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: libroadrunner>=2.10.0; extra == 'dev' Handling matplotlib>=3.11.1; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: matplotlib>=3.11.1; extra == 'dev' Handling mkdocstrings-python>=2.0.8; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: mkdocstrings-python>=2.0.8; extra == 'dev' Handling pre-commit>=4.6.2; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pre-commit>=4.6.2; extra == 'dev' Handling py4cytoscape>=1.13.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: py4cytoscape>=1.13.0; extra == 'dev' Handling pytest-cov>=7.1.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pytest-cov>=7.1.0; extra == 'dev' Handling pytest-xdist>=3.8.0; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pytest-xdist>=3.8.0; extra == 'dev' Handling pytest>=9.1.1; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: pytest>=9.1.1; extra == 'dev' Handling ruff>=0.16.6; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: ruff>=0.16.6; extra == 'dev' Handling tox>=4.61.2; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: tox>=4.61.2; extra == 'dev' Handling ty>=0.0.79; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: ty>=0.0.79; extra == 'dev' Handling zensical>=0.0.60; extra == 'dev' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: zensical>=0.0.60; extra == 'dev' Handling libroadrunner>=2.10.0; extra == 'examples' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: libroadrunner>=2.10.0; extra == 'examples' Handling matplotlib>=3.11.1; extra == 'examples' from hook generated metadata: Requires-Dist (sbmlutils) Ignoring alien requirement: matplotlib>=3.11.1; extra == 'examples' + cat /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-buildrequires + rm -rfv sbmlutils-0.17.0.dist-info/ removed 'sbmlutils-0.17.0.dist-info/METADATA' removed directory 'sbmlutils-0.17.0.dist-info/' + RPM_EC=0 ++ jobs -p + exit 0 Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.1vaIXe + umask 022 + cd /builddir/build/BUILD/python-sbmlutils-0.17.0-build + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CFLAGS + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CXXFLAGS + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FFLAGS + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FCFLAGS + VALAFLAGS=-g + export VALAFLAGS + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes -Clink-arg=-specs=/usr/lib/rpm/redhat/redhat-package-notes --cap-lints=warn' + export RUSTFLAGS + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes ' + export LDFLAGS + LT_SYS_LIBRARY_PATH=/usr/lib64: + export LT_SYS_LIBRARY_PATH + CC=gcc + export CC + CXX=g++ + export CXX + cd sbmlutils-0.17.0 + mkdir -p /builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + VALAFLAGS=-g + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes -Clink-arg=-specs=/usr/lib/rpm/redhat/redhat-package-notes --cap-lints=warn' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes ' + LT_SYS_LIBRARY_PATH=/usr/lib64: + CC=gcc + CXX=g++ + TMPDIR=/builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir + /usr/bin/python3 -Bs /usr/lib/rpm/redhat/pyproject_wheel.py /builddir/build/BUILD/python-sbmlutils-0.17.0-build/pyproject-wheeldir Processing ./. Preparing metadata (pyproject.toml): started Running command Preparing metadata (pyproject.toml) Preparing metadata (pyproject.toml): finished with status 'done' Building wheels for collected packages: sbmlutils Building wheel for sbmlutils (pyproject.toml): started Running command Building wheel for sbmlutils (pyproject.toml) Building wheel for sbmlutils (pyproject.toml): finished with status 'done' Created wheel for sbmlutils: filename=sbmlutils-0.17.0-py3-none-any.whl size=3633281 sha256=24077200b5478ab5675ac18615b17f2d3fac3025d7b1e5f52581415b5e299a63 Stored in directory: /builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir/pip-ephem-wheel-cache-dqckhsi6/wheels/2e/67/10/8e07428058ef33b3773c94ce2abc4bdc4e87805ea5723e00bb Successfully built sbmlutils + RPM_EC=0 ++ jobs -p + exit 0 Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.JeEKQM + umask 022 + cd /builddir/build/BUILD/python-sbmlutils-0.17.0-build + '[' /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT '!=' / ']' + rm -rf /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT ++ dirname /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT + mkdir -p /builddir/build/BUILD/python-sbmlutils-0.17.0-build + mkdir /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CFLAGS + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CXXFLAGS + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FFLAGS + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FCFLAGS + VALAFLAGS=-g + export VALAFLAGS + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes -Clink-arg=-specs=/usr/lib/rpm/redhat/redhat-package-notes --cap-lints=warn' + export RUSTFLAGS + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes ' + export LDFLAGS + LT_SYS_LIBRARY_PATH=/usr/lib64: + export LT_SYS_LIBRARY_PATH + CC=gcc + export CC + CXX=g++ + export CXX + cd sbmlutils-0.17.0 ++ ls /builddir/build/BUILD/python-sbmlutils-0.17.0-build/pyproject-wheeldir/sbmlutils-0.17.0-py3-none-any.whl ++ xargs basename --multiple ++ sed -E 's/([^-]+)-([^-]+)-.+\.whl/\1==\2/' + specifier=sbmlutils==0.17.0 + '[' -z sbmlutils==0.17.0 ']' + PIP_CONFIG_FILE=/dev/null + TMPDIR=/builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir + /usr/bin/python3 -m pip install --root /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT --prefix /usr --no-deps --disable-pip-version-check --progress-bar off --verbose --ignore-installed --no-warn-script-location --no-index --no-cache-dir --find-links /builddir/build/BUILD/python-sbmlutils-0.17.0-build/pyproject-wheeldir sbmlutils==0.17.0 Using pip 26.2.1 from /usr/lib/python3.15/site-packages/pip (python 3.15) Looking in links: /builddir/build/BUILD/python-sbmlutils-0.17.0-build/pyproject-wheeldir Processing /builddir/build/BUILD/python-sbmlutils-0.17.0-build/pyproject-wheeldir/sbmlutils-0.17.0-py3-none-any.whl Installing collected packages: sbmlutils Successfully installed sbmlutils-0.17.0 + '[' -d /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/bin ']' + rm -f /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-ghost-distinfo + site_dirs=() + '[' -d /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages ']' + site_dirs+=("/usr/lib/python3.15/site-packages") + '[' /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib64/python3.15/site-packages '!=' /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages ']' + '[' -d /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib64/python3.15/site-packages ']' + for site_dir in ${site_dirs[@]} + for distinfo in /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT$site_dir/*.dist-info + echo '%ghost %dir /usr/lib/python3.15/site-packages/sbmlutils-0.17.0.dist-info' +++ basename /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils-0.17.0.dist-info ++ PYTHONPATH=/usr/lib/rpm/redhat ++ /usr/bin/python3 -sBc 'import sys; from pyproject_save_files import canonical_name_from_distinfo; print(canonical_name_from_distinfo(sys.argv[1]))' sbmlutils-0.17.0.dist-info + _normalized=sbmlutils + echo '%ghost %dir /usr/lib/python3.15/site-packages/sbmlutils-0.17.0.dist-info' + sed -i s/pip/rpm/ /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils-0.17.0.dist-info/INSTALLER + PYTHONPATH=/usr/lib/rpm/redhat + /usr/bin/python3 -B /usr/lib/rpm/redhat/pyproject_preprocess_record.py --buildroot /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT --record /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils-0.17.0.dist-info/RECORD --output /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-record + rm -fv /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils-0.17.0.dist-info/RECORD removed '/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils-0.17.0.dist-info/RECORD' + rm -fv /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils-0.17.0.dist-info/REQUESTED removed '/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils-0.17.0.dist-info/REQUESTED' + '[' -f /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-dep-overrides ']' ++ wc -l /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-ghost-distinfo ++ cut -f1 '-d ' + lines=1 + '[' 1 -ne 1 ']' + RPM_FILES_ESCAPE=4.19 + /usr/bin/python3 /usr/lib/rpm/redhat/pyproject_save_files.py --output-files /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-files --output-modules /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-modules --buildroot /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT --sitelib /usr/lib/python3.15/site-packages --sitearch /usr/lib64/python3.15/site-packages --python-version 3.15 --pyproject-record /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc46.x86_64-pyproject-record --prefix /usr -l sbmlutils + /usr/lib/rpm/check-buildroot + /usr/lib/rpm/redhat/brp-ldconfig + COMPRESS='gzip -9 -n' + COMPRESS_EXT=.gz + /usr/lib/rpm/brp-compress + /usr/lib/rpm/brp-strip /usr/bin/strip + /usr/lib/rpm/brp-strip-comment-note /usr/bin/strip /usr/bin/objdump + /usr/lib/rpm/redhat/brp-strip-lto /usr/bin/strip + /usr/lib/rpm/check-rpaths + /usr/lib/rpm/redhat/brp-mangle-shebangs *** WARNING: ./usr/lib/python3.15/site-packages/sbmlutils/resources/xslt/pmml2tex/run is executable but has no shebang, removing executable bit *** WARNING: ./usr/lib/python3.15/site-packages/sbmlutils/resources/xslt/pmml2tex/pmml2texfrag.xsl is executable but has no shebang, removing executable bit *** WARNING: ./usr/lib/python3.15/site-packages/sbmlutils/resources/xslt/pmml2tex/pmml2tex.xsl is executable but has no shebang, removing executable bit *** WARNING: ./usr/lib/python3.15/site-packages/sbmlutils/resources/xslt/pmml2tex/pmml-new.sty is executable but has no shebang, removing executable bit *** WARNING: ./usr/lib/python3.15/site-packages/sbmlutils/resources/xslt/pmml2tex/mml2tex.xsl is executable but has no shebang, removing executable bit *** WARNING: ./usr/lib/python3.15/site-packages/sbmlutils/resources/xslt/pmml2tex/csscolor.sty is executable but has no shebang, removing executable bit + /usr/lib/rpm/brp-remove-la-files + /usr/lib/rpm/redhat/brp-python-rpm-in-distinfo + env /usr/lib/rpm/redhat/brp-python-bytecompile '' 1 0 -j4 Bytecompiling .py files below /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15 using python3.15 + /usr/lib/rpm/redhat/brp-python-hardlink + /usr/bin/add-det --brp -j4 /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/__pycache__/utils.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/__pycache__/notes.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/__pycache__/log.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/__pycache__/reaction_equation.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/__pycache__/console.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/__pycache__/cytoscape.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/__pycache__/biomodels.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/__pycache__/_antimony.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/resources/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/__pycache__/parser.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/__pycache__/validation.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/report/__pycache__/units.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/report/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/__pycache__/miriam.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/report/__pycache__/mathml.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/report/__pycache__/sbmlreport.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/manipulation/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/__pycache__/validator.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/manipulation/__pycache__/merge.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/layout/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/io/__pycache__/sbml.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/layout/__pycache__/layout.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/io/__pycache__/antimony.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/io/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/io/__pycache__/files.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/fbc/__pycache__/fbc.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/fbc/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/fbc/__pycache__/cobra.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/__pycache__/annotator.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/__pycache__/fbc.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/report/__pycache__/sbmlinfo.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/__pycache__/distrib.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/__pycache__/model.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/__pycache__/comp.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/distrib/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/__pycache__/units.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/data/__pycache__/interpolation.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/data/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/converters/__pycache__/xpp_helpers.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/__pycache__/_core.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/converters/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/converters/__pycache__/copasi.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/converters/ode/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/data/__pycache__/_driving.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/comp/__pycache__/flatten.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/comp/__pycache__/__init__.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/comp/__pycache__/comp.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/converters/__pycache__/xpp.cpython-315.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/__pycache__/core_elements.cpython-315.opt-1.pyc: rewriting with normalized contents Scanned 63 directories and 381 files, processed 61 inodes, 52 modified (0 replaced + 52 rewritten), 0 unsupported format, 0 errors + /usr/bin/linkdupes --brp /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr Scanned 62 directories and 381 files, considered 381 files, read 110 files, linked 7 files, 0 errors sum of sizes of linked files: 49769 bytes Executing(%check): /bin/sh -e /var/tmp/rpm-tmp.Hn4Piw + umask 022 + cd /builddir/build/BUILD/python-sbmlutils-0.17.0-build + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CFLAGS + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CXXFLAGS + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FFLAGS + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FCFLAGS + VALAFLAGS=-g + export VALAFLAGS + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes -Clink-arg=-specs=/usr/lib/rpm/redhat/redhat-package-notes --cap-lints=warn' + export RUSTFLAGS + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes ' + export LDFLAGS + LT_SYS_LIBRARY_PATH=/usr/lib64: + export LT_SYS_LIBRARY_PATH + CC=gcc + export CC + CXX=g++ + export CXX + cd sbmlutils-0.17.0 + /usr/bin/python3 -c 'import libsbml, sys; sys.exit(0 if hasattr(libsbml, "DISTRIB_UNCERTTYPE_COEFFIENTOFVARIATION") else 1)' + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes ' + PATH=/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin + PYTHONPATH=/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib64/python3.15/site-packages:/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages + PYTHONDONTWRITEBYTECODE=1 + PYTEST_ADDOPTS=' --ignore=/builddir/build/BUILD/python-sbmlutils-0.17.0-build/.pyproject-builddir' + PYTEST_XDIST_AUTO_NUM_WORKERS=4 + /usr/bin/pytest -q -m 'not sbml_testsuite' --ignore=tests/test_roundtrip.py --deselect tests/interpolation/test_interpolation_docs.py::test_guide_code_blocks_run --deselect tests/test_factory_facade.py::test_api_reference_lists_the_classes_and_functions ....................................FFFFFFFF..F.FF.F....F.F...F...F..... [ 4%] ...sssss................................................................ [ 9%] ........................................................................ [ 14%] ..............................................FF........................ [ 18%] ....F..FFFFFFFFFFFFFFFF.FFFF............................................ [ 23%] ...............................................................sssss.... [ 28%] ...................s.................................................... [ 32%] .......................................F..............F..EEEEEEEEEE..... [ 37%] ........................................................................ [ 42%] ........................................................................ [ 47%] ................................FF...................................... [ 51%] ........................................F............................... [ 56%] ........................................................................ [ 61%] ........................................................................ [ 65%] ....................................................s...............ssss [ 70%] s...........ssssssss.......ssssssss......ssssssss......ssFFssFFFF...F... [ 75%] s.....FF......F............................FFFFFFFFFFFFFFFFFFFFFFFFFFFFF [ 79%] FFFFFFFFFFFFFFFFFFFF.................................................FF. [ 84%] .F.......FsFFssssss.......sss.F..FFssFFF................ssFsssssssFFFsss [ 89%] ssss...........s........................................................ [ 94%] ........................................................................ [ 98%] ................... [100%] ==================================== ERRORS ==================================== ___ ERROR at setup of test_uncert_child_writes_meta_id_and_sbo_term[up_mean] ___ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: @pytest.fixture def uncert_metadata_doc() -> libsbml.SBMLDocument: """Write an uncertainty whose children carry every metadata field. The model is serialized and read back, so that the assertions are made on a document which went through the SBML writer and parser, not on the objects the factory created. Returns: the document read back from the written SBML; the test has to hold it, libsbml objects do not keep their document alive """ model = Model( "uncert_metadata", packages=[Package.DISTRIB_V1, Package.FBC_V3], parameters=[ Parameter( "p1", value=1.0, uncertainties=[ Uncertainty( "u1", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=5.0, sid="up_mean", name="mean of p1", metaId="meta_up_mean", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="mean of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], uncertSpans=[ UncertSpan( type=libsbml.DISTRIB_UNCERTTYPE_RANGE, valueLower=1.0, valueUpper=9.0, sid="up_range", name="range of p1", metaId="meta_up_range", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="range of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], ) ], ) ], ) > doc: libsbml.SBMLDocument = Document(model=model).create_sbml() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_distrib.py:644: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log setup ------------------------------ WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Uncertainty(u1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Uncertainty(u1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) __ ERROR at setup of test_uncert_child_writes_meta_id_and_sbo_term[up_range] ___ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: @pytest.fixture def uncert_metadata_doc() -> libsbml.SBMLDocument: """Write an uncertainty whose children carry every metadata field. The model is serialized and read back, so that the assertions are made on a document which went through the SBML writer and parser, not on the objects the factory created. Returns: the document read back from the written SBML; the test has to hold it, libsbml objects do not keep their document alive """ model = Model( "uncert_metadata", packages=[Package.DISTRIB_V1, Package.FBC_V3], parameters=[ Parameter( "p1", value=1.0, uncertainties=[ Uncertainty( "u1", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=5.0, sid="up_mean", name="mean of p1", metaId="meta_up_mean", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="mean of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], uncertSpans=[ UncertSpan( type=libsbml.DISTRIB_UNCERTTYPE_RANGE, valueLower=1.0, valueUpper=9.0, sid="up_range", name="range of p1", metaId="meta_up_range", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="range of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], ) ], ) ], ) > doc: libsbml.SBMLDocument = Document(model=model).create_sbml() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_distrib.py:644: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log setup ------------------------------ WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Uncertainty(u1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Uncertainty(u1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _______ ERROR at setup of test_uncert_child_writes_id_and_name[up_mean] ________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: @pytest.fixture def uncert_metadata_doc() -> libsbml.SBMLDocument: """Write an uncertainty whose children carry every metadata field. The model is serialized and read back, so that the assertions are made on a document which went through the SBML writer and parser, not on the objects the factory created. Returns: the document read back from the written SBML; the test has to hold it, libsbml objects do not keep their document alive """ model = Model( "uncert_metadata", packages=[Package.DISTRIB_V1, Package.FBC_V3], parameters=[ Parameter( "p1", value=1.0, uncertainties=[ Uncertainty( "u1", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=5.0, sid="up_mean", name="mean of p1", metaId="meta_up_mean", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="mean of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], uncertSpans=[ UncertSpan( type=libsbml.DISTRIB_UNCERTTYPE_RANGE, valueLower=1.0, valueUpper=9.0, sid="up_range", name="range of p1", metaId="meta_up_range", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="range of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], ) ], ) ], ) > doc: libsbml.SBMLDocument = Document(model=model).create_sbml() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_distrib.py:644: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log setup ------------------------------ WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Uncertainty(u1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Uncertainty(u1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _______ ERROR at setup of test_uncert_child_writes_id_and_name[up_range] _______ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: @pytest.fixture def uncert_metadata_doc() -> libsbml.SBMLDocument: """Write an uncertainty whose children carry every metadata field. The model is serialized and read back, so that the assertions are made on a document which went through the SBML writer and parser, not on the objects the factory created. Returns: the document read back from the written SBML; the test has to hold it, libsbml objects do not keep their document alive """ model = Model( "uncert_metadata", packages=[Package.DISTRIB_V1, Package.FBC_V3], parameters=[ Parameter( "p1", value=1.0, uncertainties=[ Uncertainty( "u1", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=5.0, sid="up_mean", name="mean of p1", metaId="meta_up_mean", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="mean of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], uncertSpans=[ UncertSpan( type=libsbml.DISTRIB_UNCERTTYPE_RANGE, valueLower=1.0, valueUpper=9.0, sid="up_range", name="range of p1", metaId="meta_up_range", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="range of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], ) ], ) ], ) > doc: libsbml.SBMLDocument = Document(model=model).create_sbml() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_distrib.py:644: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log setup ------------------------------ WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Uncertainty(u1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Uncertainty(u1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) __________ ERROR at setup of test_uncert_child_writes_notes[up_mean] ___________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: @pytest.fixture def uncert_metadata_doc() -> libsbml.SBMLDocument: """Write an uncertainty whose children carry every metadata field. The model is serialized and read back, so that the assertions are made on a document which went through the SBML writer and parser, not on the objects the factory created. Returns: the document read back from the written SBML; the test has to hold it, libsbml objects do not keep their document alive """ model = Model( "uncert_metadata", packages=[Package.DISTRIB_V1, Package.FBC_V3], parameters=[ Parameter( "p1", value=1.0, uncertainties=[ Uncertainty( "u1", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=5.0, sid="up_mean", name="mean of p1", metaId="meta_up_mean", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="mean of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], uncertSpans=[ UncertSpan( type=libsbml.DISTRIB_UNCERTTYPE_RANGE, valueLower=1.0, valueUpper=9.0, sid="up_range", name="range of p1", metaId="meta_up_range", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="range of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], ) ], ) ], ) > doc: libsbml.SBMLDocument = Document(model=model).create_sbml() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_distrib.py:644: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log setup ------------------------------ WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Uncertainty(u1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Uncertainty(u1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) __________ ERROR at setup of test_uncert_child_writes_notes[up_range] __________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: @pytest.fixture def uncert_metadata_doc() -> libsbml.SBMLDocument: """Write an uncertainty whose children carry every metadata field. The model is serialized and read back, so that the assertions are made on a document which went through the SBML writer and parser, not on the objects the factory created. Returns: the document read back from the written SBML; the test has to hold it, libsbml objects do not keep their document alive """ model = Model( "uncert_metadata", packages=[Package.DISTRIB_V1, Package.FBC_V3], parameters=[ Parameter( "p1", value=1.0, uncertainties=[ Uncertainty( "u1", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=5.0, sid="up_mean", name="mean of p1", metaId="meta_up_mean", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="mean of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], uncertSpans=[ UncertSpan( type=libsbml.DISTRIB_UNCERTTYPE_RANGE, valueLower=1.0, valueUpper=9.0, sid="up_range", name="range of p1", metaId="meta_up_range", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="range of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], ) ], ) ], ) > doc: libsbml.SBMLDocument = Document(model=model).create_sbml() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_distrib.py:644: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log setup ------------------------------ WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Uncertainty(u1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Uncertainty(u1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _______ ERROR at setup of test_uncert_child_writes_annotations[up_mean] ________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: @pytest.fixture def uncert_metadata_doc() -> libsbml.SBMLDocument: """Write an uncertainty whose children carry every metadata field. The model is serialized and read back, so that the assertions are made on a document which went through the SBML writer and parser, not on the objects the factory created. Returns: the document read back from the written SBML; the test has to hold it, libsbml objects do not keep their document alive """ model = Model( "uncert_metadata", packages=[Package.DISTRIB_V1, Package.FBC_V3], parameters=[ Parameter( "p1", value=1.0, uncertainties=[ Uncertainty( "u1", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=5.0, sid="up_mean", name="mean of p1", metaId="meta_up_mean", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="mean of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], uncertSpans=[ UncertSpan( type=libsbml.DISTRIB_UNCERTTYPE_RANGE, valueLower=1.0, valueUpper=9.0, sid="up_range", name="range of p1", metaId="meta_up_range", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="range of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], ) ], ) ], ) > doc: libsbml.SBMLDocument = Document(model=model).create_sbml() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_distrib.py:644: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log setup ------------------------------ WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Uncertainty(u1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Uncertainty(u1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _______ ERROR at setup of test_uncert_child_writes_annotations[up_range] _______ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: @pytest.fixture def uncert_metadata_doc() -> libsbml.SBMLDocument: """Write an uncertainty whose children carry every metadata field. The model is serialized and read back, so that the assertions are made on a document which went through the SBML writer and parser, not on the objects the factory created. Returns: the document read back from the written SBML; the test has to hold it, libsbml objects do not keep their document alive """ model = Model( "uncert_metadata", packages=[Package.DISTRIB_V1, Package.FBC_V3], parameters=[ Parameter( "p1", value=1.0, uncertainties=[ Uncertainty( "u1", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=5.0, sid="up_mean", name="mean of p1", metaId="meta_up_mean", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="mean of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], uncertSpans=[ UncertSpan( type=libsbml.DISTRIB_UNCERTTYPE_RANGE, valueLower=1.0, valueUpper=9.0, sid="up_range", name="range of p1", metaId="meta_up_range", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="range of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], ) ], ) ], ) > doc: libsbml.SBMLDocument = Document(model=model).create_sbml() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_distrib.py:644: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log setup ------------------------------ WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Uncertainty(u1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Uncertainty(u1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _____ ERROR at setup of test_uncert_child_writes_key_value_pairs[up_mean] ______ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: @pytest.fixture def uncert_metadata_doc() -> libsbml.SBMLDocument: """Write an uncertainty whose children carry every metadata field. The model is serialized and read back, so that the assertions are made on a document which went through the SBML writer and parser, not on the objects the factory created. Returns: the document read back from the written SBML; the test has to hold it, libsbml objects do not keep their document alive """ model = Model( "uncert_metadata", packages=[Package.DISTRIB_V1, Package.FBC_V3], parameters=[ Parameter( "p1", value=1.0, uncertainties=[ Uncertainty( "u1", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=5.0, sid="up_mean", name="mean of p1", metaId="meta_up_mean", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="mean of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], uncertSpans=[ UncertSpan( type=libsbml.DISTRIB_UNCERTTYPE_RANGE, valueLower=1.0, valueUpper=9.0, sid="up_range", name="range of p1", metaId="meta_up_range", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="range of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], ) ], ) ], ) > doc: libsbml.SBMLDocument = Document(model=model).create_sbml() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_distrib.py:644: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log setup ------------------------------ WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Uncertainty(u1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Uncertainty(u1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _____ ERROR at setup of test_uncert_child_writes_key_value_pairs[up_range] _____ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: @pytest.fixture def uncert_metadata_doc() -> libsbml.SBMLDocument: """Write an uncertainty whose children carry every metadata field. The model is serialized and read back, so that the assertions are made on a document which went through the SBML writer and parser, not on the objects the factory created. Returns: the document read back from the written SBML; the test has to hold it, libsbml objects do not keep their document alive """ model = Model( "uncert_metadata", packages=[Package.DISTRIB_V1, Package.FBC_V3], parameters=[ Parameter( "p1", value=1.0, uncertainties=[ Uncertainty( "u1", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=5.0, sid="up_mean", name="mean of p1", metaId="meta_up_mean", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="mean of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], uncertSpans=[ UncertSpan( type=libsbml.DISTRIB_UNCERTTYPE_RANGE, valueLower=1.0, valueUpper=9.0, sid="up_range", name="range of p1", metaId="meta_up_range", sboTerm=UNCERT_SBO, annotations=[(BQB.IS, "chebi/CHEBI:15377")], notes="range of the measurements", keyValuePairs=[ KeyValuePair( key="source", value="sabiork", uri="https://example.org/kvp", ) ], ) ], ) ], ) ], ) > doc: libsbml.SBMLDocument = Document(model=model).create_sbml() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_distrib.py:644: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log setup ------------------------------ WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Uncertainty(u1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Uncertainty(u1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(u1, UncertSpan(15, 1.0 - 9.0 [None]), UncertParameter(4, 5.0 [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) =================================== FAILURES =================================== _________________ test_example_script[examples.converters.xpp] _________________ module = 'examples.converters.xpp' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_example_script_examples_c0') @pytest.mark.parametrize("module", SCRIPTS) def test_example_script(module: str, tmp_path: Path) -> None: """Every example runs without an error and writes into the working directory.""" if module in { "examples.converters.xpp", "examples.interpolation.driving", "examples.interpolation.interpolation", "examples.interpolation.pancreas", "examples.tiny.simulation", }: pytest.importorskip("roadrunner") env = dict(os.environ, PYTHONPATH=str(REPO_DIR), MPLBACKEND="Agg") result = subprocess.run( [sys.executable, "-m", module], cwd=tmp_path, env=env, capture_output=True, text=True, check=False, ) > assert result.returncode == 0, result.stderr E AssertionError: Traceback (most recent call last): E File "", line 201, in _run_module_as_main E File "", line 87, in _run_code E File "/builddir/build/BUILD/python-sbmlutils-0.17.0-build/sbmlutils-0.17.0/examples/converters/xpp.py", line 24, in E from sbmlutils.converters import xpp E ModuleNotFoundError: No module named 'sbmlutils' E E assert 1 == 0 E + where 1 = CompletedProcess(args=['/usr/bin/python3', '-m', 'examples.converters.xpp'], returncode=1, stdout='', stderr='Tracebac... line 24, in \n from sbmlutils.converters import xpp\nModuleNotFoundError: No module named \'sbmlutils\'\n').returncode tests/examples/test_example_scripts.py:55: AssertionError _______ test_example_script[examples.distrib.distrib_packages_examples] ________ module = 'examples.distrib.distrib_packages_examples' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_example_script_examples_d0') @pytest.mark.parametrize("module", SCRIPTS) def test_example_script(module: str, tmp_path: Path) -> None: """Every example runs without an error and writes into the working directory.""" if module in { "examples.converters.xpp", "examples.interpolation.driving", "examples.interpolation.interpolation", "examples.interpolation.pancreas", "examples.tiny.simulation", }: pytest.importorskip("roadrunner") env = dict(os.environ, PYTHONPATH=str(REPO_DIR), MPLBACKEND="Agg") result = subprocess.run( [sys.executable, "-m", module], cwd=tmp_path, env=env, capture_output=True, text=True, check=False, ) > assert result.returncode == 0, result.stderr E AssertionError: Traceback (most recent call last): E File "", line 201, in _run_module_as_main E File "", line 87, in _run_code E File "/builddir/build/BUILD/python-sbmlutils-0.17.0-build/sbmlutils-0.17.0/examples/distrib/distrib_packages_examples.py", line 18, in E from sbmlutils import validation E ModuleNotFoundError: No module named 'sbmlutils' E E assert 1 == 0 E + where 1 = CompletedProcess(args=['/usr/bin/python3', '-m', 'examples.distrib.distrib_packages_examples'], returncode=1, stdout='...py", line 18, in \n from sbmlutils import validation\nModuleNotFoundError: No module named \'sbmlutils\'\n').returncode tests/examples/test_example_scripts.py:55: AssertionError __________ test_example_script[examples.distrib.distrib_uncertainty] ___________ module = 'examples.distrib.distrib_uncertainty' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_example_script_examples_d1') @pytest.mark.parametrize("module", SCRIPTS) def test_example_script(module: str, tmp_path: Path) -> None: """Every example runs without an error and writes into the working directory.""" if module in { "examples.converters.xpp", "examples.interpolation.driving", "examples.interpolation.interpolation", "examples.interpolation.pancreas", "examples.tiny.simulation", }: pytest.importorskip("roadrunner") env = dict(os.environ, PYTHONPATH=str(REPO_DIR), MPLBACKEND="Agg") result = subprocess.run( [sys.executable, "-m", module], cwd=tmp_path, env=env, capture_output=True, text=True, check=False, ) > assert result.returncode == 0, result.stderr E AssertionError: Traceback (most recent call last): E File "", line 201, in _run_module_as_main E File "", line 87, in _run_code E File "/builddir/build/BUILD/python-sbmlutils-0.17.0-build/sbmlutils-0.17.0/examples/distrib/distrib_uncertainty.py", line 19, in E from sbmlutils import RESOURCES_DIR E ModuleNotFoundError: No module named 'sbmlutils' E E assert 1 == 0 E + where 1 = CompletedProcess(args=['/usr/bin/python3', '-m', 'examples.distrib.distrib_uncertainty'], returncode=1, stdout='', std..., line 19, in \n from sbmlutils import RESOURCES_DIR\nModuleNotFoundError: No module named \'sbmlutils\'\n').returncode tests/examples/test_example_scripts.py:55: AssertionError _____________ test_example_script[examples.interpolation.driving] ______________ module = 'examples.interpolation.driving' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_example_script_examples_i0') @pytest.mark.parametrize("module", SCRIPTS) def test_example_script(module: str, tmp_path: Path) -> None: """Every example runs without an error and writes into the working directory.""" if module in { "examples.converters.xpp", "examples.interpolation.driving", "examples.interpolation.interpolation", "examples.interpolation.pancreas", "examples.tiny.simulation", }: pytest.importorskip("roadrunner") env = dict(os.environ, PYTHONPATH=str(REPO_DIR), MPLBACKEND="Agg") result = subprocess.run( [sys.executable, "-m", module], cwd=tmp_path, env=env, capture_output=True, text=True, check=False, ) > assert result.returncode == 0, result.stderr E AssertionError: Traceback (most recent call last): E File "", line 201, in _run_module_as_main E File "", line 87, in _run_code E File "/builddir/build/BUILD/python-sbmlutils-0.17.0-build/sbmlutils-0.17.0/examples/interpolation/driving.py", line 25, in E from sbmlutils.comp import flatten_sbml E ModuleNotFoundError: No module named 'sbmlutils' E E assert 1 == 0 E + where 1 = CompletedProcess(args=['/usr/bin/python3', '-m', 'examples.interpolation.driving'], returncode=1, stdout='', stderr='T...ne 25, in \n from sbmlutils.comp import flatten_sbml\nModuleNotFoundError: No module named \'sbmlutils\'\n').returncode tests/examples/test_example_scripts.py:55: AssertionError __________ test_example_script[examples.interpolation.interpolation] ___________ module = 'examples.interpolation.interpolation' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_example_script_examples_i1') @pytest.mark.parametrize("module", SCRIPTS) def test_example_script(module: str, tmp_path: Path) -> None: """Every example runs without an error and writes into the working directory.""" if module in { "examples.converters.xpp", "examples.interpolation.driving", "examples.interpolation.interpolation", "examples.interpolation.pancreas", "examples.tiny.simulation", }: pytest.importorskip("roadrunner") env = dict(os.environ, PYTHONPATH=str(REPO_DIR), MPLBACKEND="Agg") result = subprocess.run( [sys.executable, "-m", module], cwd=tmp_path, env=env, capture_output=True, text=True, check=False, ) > assert result.returncode == 0, result.stderr E AssertionError: Traceback (most recent call last): E File "", line 201, in _run_module_as_main E File "", line 87, in _run_code E File "/builddir/build/BUILD/python-sbmlutils-0.17.0-build/sbmlutils-0.17.0/examples/interpolation/interpolation.py", line 26, in E from sbmlutils.data import interpolation as ip E ModuleNotFoundError: No module named 'sbmlutils' E E assert 1 == 0 E + where 1 = CompletedProcess(args=['/usr/bin/python3', '-m', 'examples.interpolation.interpolation'], returncode=1, stdout='', std...in \n from sbmlutils.data import interpolation as ip\nModuleNotFoundError: No module named \'sbmlutils\'\n').returncode tests/examples/test_example_scripts.py:55: AssertionError _____________ test_example_script[examples.interpolation.pancreas] _____________ module = 'examples.interpolation.pancreas' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_example_script_examples_i2') @pytest.mark.parametrize("module", SCRIPTS) def test_example_script(module: str, tmp_path: Path) -> None: """Every example runs without an error and writes into the working directory.""" if module in { "examples.converters.xpp", "examples.interpolation.driving", "examples.interpolation.interpolation", "examples.interpolation.pancreas", "examples.tiny.simulation", }: pytest.importorskip("roadrunner") env = dict(os.environ, PYTHONPATH=str(REPO_DIR), MPLBACKEND="Agg") result = subprocess.run( [sys.executable, "-m", module], cwd=tmp_path, env=env, capture_output=True, text=True, check=False, ) > assert result.returncode == 0, result.stderr E AssertionError: Traceback (most recent call last): E File "", line 201, in _run_module_as_main E File "", line 87, in _run_code E File "/builddir/build/BUILD/python-sbmlutils-0.17.0-build/sbmlutils-0.17.0/examples/interpolation/pancreas.py", line 29, in E from sbmlutils.console import console E ModuleNotFoundError: No module named 'sbmlutils' E E assert 1 == 0 E + where 1 = CompletedProcess(args=['/usr/bin/python3', '-m', 'examples.interpolation.pancreas'], returncode=1, stdout='', stderr='...line 29, in \n from sbmlutils.console import console\nModuleNotFoundError: No module named \'sbmlutils\'\n').returncode tests/examples/test_example_scripts.py:55: AssertionError ___________ test_example_script[examples.merge_models.merge_models] ____________ module = 'examples.merge_models.merge_models' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_example_script_examples_m0') @pytest.mark.parametrize("module", SCRIPTS) def test_example_script(module: str, tmp_path: Path) -> None: """Every example runs without an error and writes into the working directory.""" if module in { "examples.converters.xpp", "examples.interpolation.driving", "examples.interpolation.interpolation", "examples.interpolation.pancreas", "examples.tiny.simulation", }: pytest.importorskip("roadrunner") env = dict(os.environ, PYTHONPATH=str(REPO_DIR), MPLBACKEND="Agg") result = subprocess.run( [sys.executable, "-m", module], cwd=tmp_path, env=env, capture_output=True, text=True, check=False, ) > assert result.returncode == 0, result.stderr E AssertionError: Traceback (most recent call last): E File "", line 201, in _run_module_as_main E File "", line 87, in _run_code E File "/builddir/build/BUILD/python-sbmlutils-0.17.0-build/sbmlutils-0.17.0/examples/merge_models/merge_models.py", line 17, in E from sbmlutils.console import console E ModuleNotFoundError: No module named 'sbmlutils' E E assert 1 == 0 E + where 1 = CompletedProcess(args=['/usr/bin/python3', '-m', 'examples.merge_models.merge_models'], returncode=1, stdout='', stder...line 17, in \n from sbmlutils.console import console\nModuleNotFoundError: No module named \'sbmlutils\'\n').returncode tests/examples/test_example_scripts.py:55: AssertionError ________________ test_example_script[examples.tiny.simulation] _________________ module = 'examples.tiny.simulation' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_example_script_examples_t0') @pytest.mark.parametrize("module", SCRIPTS) def test_example_script(module: str, tmp_path: Path) -> None: """Every example runs without an error and writes into the working directory.""" if module in { "examples.converters.xpp", "examples.interpolation.driving", "examples.interpolation.interpolation", "examples.interpolation.pancreas", "examples.tiny.simulation", }: pytest.importorskip("roadrunner") env = dict(os.environ, PYTHONPATH=str(REPO_DIR), MPLBACKEND="Agg") result = subprocess.run( [sys.executable, "-m", module], cwd=tmp_path, env=env, capture_output=True, text=True, check=False, ) > assert result.returncode == 0, result.stderr E AssertionError: Traceback (most recent call last): E File "", line 201, in _run_module_as_main E File "", line 87, in _run_code E File "/builddir/build/BUILD/python-sbmlutils-0.17.0-build/sbmlutils-0.17.0/examples/tiny/simulation.py", line 28, in E from examples.tiny import tiny E File "/builddir/build/BUILD/python-sbmlutils-0.17.0-build/sbmlutils-0.17.0/examples/tiny/tiny.py", line 6, in E import sbmlutils.layout as layout E ModuleNotFoundError: No module named 'sbmlutils' E E assert 1 == 0 E + where 1 = CompletedProcess(args=['/usr/bin/python3', '-m', 'examples.tiny.simulation'], returncode=1, stdout='', stderr='Traceba...py", line 6, in \n import sbmlutils.layout as layout\nModuleNotFoundError: No module named \'sbmlutils\'\n').returncode tests/examples/test_example_scripts.py:55: AssertionError _______ test_create_example_create[examples.tutorial.model_composition] ________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_create_example_create_exa2') module = @pytest.mark.parametrize("module", examples_create) def test_create_example_create(tmp_path: Path, module: Any) -> None: """Test that an example writes models and that every one of them is valid.""" > module.create(output_dir=tmp_path) tests/examples/test_examples.py:19: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ examples/tutorial/model_composition.py:26: in create return create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ________________ test_create_example_create[examples.demo.demo] ________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_create_example_create_exa4') module = @pytest.mark.parametrize("module", examples_create) def test_create_example_create(tmp_path: Path, module: Any) -> None: """Test that an example writes models and that every one of them is valid.""" > module.create(output_dir=tmp_path) tests/examples/test_examples.py:19: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ examples/demo/demo.py:213: in create create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1773: in create_model doc = annotator.annotate_sbml_doc( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:276: in annotate_sbml_doc annotator.annotate_model() ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:429: in annotate_model self._annotate_elements(elements, a) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:523: in _annotate_elements annotation = Annotation( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(scale_f, metabolic scaling factor)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Vmax_bA)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Vmax_bA)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Km_A)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Km_A)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Vmax_bB)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Vmax_bB)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Km_B)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Km_B)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Vmax_bC)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Vmax_bC)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Km_C)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Km_C)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Vmax_v1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Vmax_v1)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Keq_v1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Keq_v1)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Vmax_v2)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Vmax_v2)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Vmax_v3)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Vmax_v3)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Vmax_v4)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Vmax_v4)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(Keq_v4)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Keq_v4)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(e, external compartment)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c, cell compartment)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(m, plasma membrane)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(c__A, A)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(c__B, B)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(c__C, C)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(e__A, A)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(e__B, B)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(e__C, C)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Reaction(bA, bA (A import))' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Reaction(bB, bB (B export))' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Reaction(bC, bC (C export))' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Reaction(v1, v1 (A -> B))' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Reaction(v2, v2 (A -> C))' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Reaction(v3, v3 (C -> A))' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Reaction(v4, v4 (C -> B))' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ________________ test_create_example_create[examples.tiny.tiny] ________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_create_example_create_exa5') module = @pytest.mark.parametrize("module", examples_create) def test_create_example_create(tmp_path: Path, module: Any) -> None: """Test that an example writes models and that every one of them is valid.""" > module.create(output_dir=tmp_path) tests/examples/test_examples.py:19: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ examples/tiny/tiny.py:434: in create return create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1773: in create_model doc = annotator.annotate_sbml_doc( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:276: in annotate_sbml_doc annotator.annotate_model() ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:429: in annotate_model self._annotate_elements(elements, a) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:523: in _annotate_elements annotation = Annotation( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Function(f_oscillation)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Function(f_oscillation)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(minus_1000, SBO_0000625)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(plus_1000, SBO_0000625)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c, cell compartment, True)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'InitialAssignment()' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'InitialAssignment()' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(a_sum, ATP + ADP balance)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Event(event_1, reset concentrations)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Constraint(constraint_1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Constraint(constraint_1)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Objective(atp_consume_max)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Objective(atp_consume_max)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'FluxObjective()' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'FluxObjective()' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Layout(layout_1, Layout 1)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'SpeciesGlyph(glyph_atp)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'SpeciesGlyph(glyph_atp)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'SpeciesGlyph(glyph_adp)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'SpeciesGlyph(glyph_adp)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'SpeciesGlyph(glyph_glc)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'SpeciesGlyph(glyph_glc)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'SpeciesGlyph(glyph_g6p)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'SpeciesGlyph(glyph_g6p)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'SpeciesGlyph(glyph_hydron)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'SpeciesGlyph(glyph_hydron)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'ReactionGlyph(glyph_GK)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'ReactionGlyph(glyph_GK)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'ReactionGlyph(glyph_ATPPROD)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'ReactionGlyph(glyph_ATPPROD)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING sbmlutils.factory._core:_core.py:250 The 'name' of 1 element(s) is not written: SBML L3V1 has no such attribute, e.g. 'AssignmentRule(ATP + ADP balance)'. Write SBML Level 3 Version 2 to keep it. WARNING sbmlutils.factory._core:_core.py:250 The 'id' of 1 element(s) is not written: SBML L3V1 has no such attribute, e.g. 'Constraint(constraint_1)'. Write SBML Level 3 Version 2 to keep it. _______________ test_create_example_models[examples.annotation] ________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_create_example_models_exa1') module = @pytest.mark.parametrize("module", examples_models) def test_create_example_models(tmp_path: Path, module: Any) -> None: """Test create model.""" model_path: Path = tmp_path / "model.xml" > results = create_model( model=module.model, filepath=model_path, ) tests/examples/test_examples.py:35: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:314: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:340: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(x_cell, cell diameter)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Vol_e, external volume)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(A_m, membrane area)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Compartment(ext, external, SBO_0000290)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _______________ test_create_example_models[examples.fbc.fbc_v2] ________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_create_example_models_exa6') module = @pytest.mark.parametrize("module", examples_models) def test_create_example_models(tmp_path: Path, module: Any) -> None: """Test create model.""" model_path: Path = tmp_path / "model.xml" > results = create_model( model=module.model, filepath=model_path, ) tests/examples/test_examples.py:35: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/fbc.py:145: in create_sbml self._set_fields(gene_product, model=model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(bioreactor, bioreactor)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(Glcxt, glucose)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(Ac, acetate)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(O2, oxygen)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(X, biomass)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s_Rv0649, s_Rv0649 (GeneProduct))' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'GeneProduct(gene1, meta_gene_1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'GeneProduct(gene1, meta_gene_1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'GeneProduct(gene1, meta_gene_1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ___________ test_create_example_models[examples.fbc.fbc_mass_charge] ___________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_create_example_models_exa8') module = @pytest.mark.parametrize("module", examples_models) def test_create_example_models(tmp_path: Path, module: Any) -> None: """Test create model.""" model_path: Path = tmp_path / "model.xml" > results = create_model( model=module.model, filepath=model_path, ) tests/examples/test_examples.py:35: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:314: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:340: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(HEX1_v)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(HEX1_v)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Compartment(cyto, cytosol, SBO_0000290)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) __________________ test_create_example_models[examples.model] __________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_create_example_models_exa12') module = @pytest.mark.parametrize("module", examples_models) def test_create_example_models(tmp_path: Path, module: Any) -> None: """Test create model.""" model_path: Path = tmp_path / "model.xml" > results = create_model( model=module.model, filepath=model_path, ) tests/examples/test_examples.py:35: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:314: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:340: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(k1, SBO_0000009)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(cell, SBO_0000290, meta_cell, [Uncertainty(UncertSpan(15, 0.2 - 3.0 [None]), UncertParameter(4, 1.0 [None]), UncertParameter(9, 0.1 [None]), UncertParameter(0, None [None]))])' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Compartment(cell, SBO_0000290, meta_cell, [Uncertainty(UncertSpan(15, 0.2 - 3.0 [None]), UncertParameter(4, 1.0 [None]), UncertParameter(9, 0.1 [None]), UncertParameter(0, None [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ________________ test_create_example_models[examples.parameter] ________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_create_example_models_exa16') module = @pytest.mark.parametrize("module", examples_models) def test_create_example_models(tmp_path: Path, module: Any) -> None: """Test create model.""" model_path: Path = tmp_path / "model.xml" > results = create_model( model=module.model, filepath=model_path, ) tests/examples/test_examples.py:35: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p1)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p2)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p2)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p3)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p3)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p4)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p4)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(dose, SBO_0000002, meta_dose)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(dose, SBO_0000002, meta_dose)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ________ test_read_sbml_reads_a_file_without_an_xml_declaration[model] _________ tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_read_sbml_reads_a_file_wi1') content = '' @pytest.mark.parametrize( "content", [ pytest.param( _SBML_NO_DECLARATION.replace("/>", '>'), id="model", ), pytest.param( _SBML_COMP_LIBRARY.removeprefix(''), id="comp-library", ), ], ) def test_read_sbml_reads_a_file_without_an_xml_declaration( tmp_path: Path, content: str ) -> None: """A missing declaration is an error of the document, it was read in full. libsbml reports `MissingXMLEncoding` and `BadXMLDecl` for it, both of severity error; the document is kept with them for the validation. """ sbml_path = tmp_path / "model.xml" sbml_path.write_text(content, encoding="utf-8") doc = read_sbml(sbml_path) assert doc.getModel() is not None or ( doc.getPlugin("comp").getNumModelDefinitions() == 1 ) > assert libsbml.BadXMLDecl in {e[0] for e in _errors(doc)} E assert 1003 in {1002} E + where 1003 = libsbml.BadXMLDecl tests/io/test_sbml.py:575: AssertionError ------------------------------ Captured log call ------------------------------- ERROR sbmlutils.validation:validation.py:522 [black on white]ENone: XML content (core, L1, code)[/black on white] [error][on black][Error] Missing XML encoding attribute[/on black][/error] Missing encoding attribute in XML declaration. ERROR sbmlutils.io.sbml:sbml.py:75 `read_sbml`: errors encountered while reading the SBML file '/tmp/pytest-of-mockbuild/pytest-0/test_read_sbml_reads_a_file_wi1/model.xml'. _____ test_read_sbml_reads_a_file_without_an_xml_declaration[comp-library] _____ tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_read_sbml_reads_a_file_wi2') content = '' @pytest.mark.parametrize( "content", [ pytest.param( _SBML_NO_DECLARATION.replace("/>", '>'), id="model", ), pytest.param( _SBML_COMP_LIBRARY.removeprefix(''), id="comp-library", ), ], ) def test_read_sbml_reads_a_file_without_an_xml_declaration( tmp_path: Path, content: str ) -> None: """A missing declaration is an error of the document, it was read in full. libsbml reports `MissingXMLEncoding` and `BadXMLDecl` for it, both of severity error; the document is kept with them for the validation. """ sbml_path = tmp_path / "model.xml" sbml_path.write_text(content, encoding="utf-8") doc = read_sbml(sbml_path) assert doc.getModel() is not None or ( doc.getPlugin("comp").getNumModelDefinitions() == 1 ) > assert libsbml.BadXMLDecl in {e[0] for e in _errors(doc)} E assert 1003 in {1002} E + where 1003 = libsbml.BadXMLDecl tests/io/test_sbml.py:575: AssertionError ------------------------------ Captured log call ------------------------------- ERROR sbmlutils.validation:validation.py:522 [black on white]ENone: XML content (core, L1, code)[/black on white] [error][on black][Error] Missing XML encoding attribute[/on black][/error] Missing encoding attribute in XML declaration. ERROR sbmlutils.io.sbml:sbml.py:75 `read_sbml`: errors encountered while reading the SBML file '/tmp/pytest-of-mockbuild/pytest-0/test_read_sbml_reads_a_file_wi2/model.xml'. ____________________________ test_create_annotation ____________________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_create_annotation0') def test_create_annotation(tmp_path: Path) -> None: """Create assignment model.""" model_path: Path = tmp_path / "model.xml" > create_model(annotation_example.model, filepath=model_path) tests/metadata/test_annotator.py:32: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:314: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:340: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(x_cell, cell diameter)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(Vol_e, external volume)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(A_m, membrane area)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Compartment(ext, external, SBO_0000290)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ____________________________ test_model_annotation _____________________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_model_annotation0') def test_model_annotation(tmp_path: Path) -> None: """Create minimal model and check that annotation is written correctly.""" model_dict: ModelDict = { "sid": "example_annotation", "compartments": [ Compartment( sid="C", value=1.0, sboTerm=SBO.PHYSICAL_COMPARTMENT, annotations=[ (BQB.IS, "chebi/CHEBI:28061"), # alpha-D-galactose ], ) ], } > results = create_model( model=Model(**model_dict), filepath=tmp_path / "annotation1.xml" ) tests/metadata/test_annotator.py:83: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:314: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:340: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(C, SBO_0000290)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Compartment(C, SBO_0000290)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _____________________________ test_demo_annotation _____________________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_demo_annotation0') def test_demo_annotation(tmp_path: Path) -> None: """Annotate the demo network.""" tmp_sbml_path = tmp_path / "sbml_annotated.xml" > annotator.annotate_sbml( DEMO_SBML_NO_ANNOTATIONS, DEMO_ANNOTATIONS, filepath=tmp_sbml_path ) tests/metadata/test_annotator.py:106: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:257: in annotate_sbml doc = annotate_sbml_doc(doc, external_annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:276: in annotate_sbml_doc annotator.annotate_model() ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:429: in annotate_model self._annotate_elements(elements, a) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:523: in _annotate_elements annotation = Annotation( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset __________________________ test_galactose_annotation ___________________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_galactose_annotation0') def test_galactose_annotation(tmp_path: Path) -> None: """Annotate the galactose network from the annotations of a spreadsheet.""" assert ( _annotated_elements(read_sbml(GALACTOSE_SINGLECELL_SBML_NO_ANNOTATIONS)) == [] ) tmp_sbml_path = tmp_path / "sbml_annotated.xml" > annotator.annotate_sbml( GALACTOSE_SINGLECELL_SBML_NO_ANNOTATIONS, annotations_path=GALACTOSE_ANNOTATIONS, filepath=tmp_sbml_path, ) tests/metadata/test_annotator.py:219: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:257: in annotate_sbml doc = annotate_sbml_doc(doc, external_annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:276: in annotate_sbml_doc annotator.annotate_model() ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:429: in annotate_model self._annotate_elements(elements, a) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/metadata/annotator.py:523: in _annotate_elements annotation = Annotation( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_annotation_resource_which_cannot_be_normalized_is_written_as_given[urn:miriam:sbmlutils.test.collection1] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:sbmlutils.test.collection1' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_which0') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eaa61e250> @pytest.mark.parametrize("resource", LOSSY_RESOURCES) def test_annotation_resource_which_cannot_be_normalized_is_written_as_given( resource: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource is written as given rather than as something else. An annotation is written as `RDFAnnotation.resource_normalized`, which does not exist for a resource without a term and is not a resource of identifiers.org any more for one without a collection. Writing either would make the annotation say something else than the model definition did. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:350: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING pymetadata.core.annotation:annotation.py:295 Deprecated urn pattern `urn:miriam:sbmlutils.test.collection1` updated: None WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_which_cannot_be_normalized_is_written_as_given[urn:miriam:sbmlutils.test.collection1:] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:sbmlutils.test.collection1:' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_which1') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eaa9a5370> @pytest.mark.parametrize("resource", LOSSY_RESOURCES) def test_annotation_resource_which_cannot_be_normalized_is_written_as_given( resource: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource is written as given rather than as something else. An annotation is written as `RDFAnnotation.resource_normalized`, which does not exist for a resource without a term and is not a resource of identifiers.org any more for one without a collection. Writing either would make the annotation say something else than the model definition did. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:350: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING pymetadata.core.annotation:annotation.py:295 Deprecated urn pattern `urn:miriam:sbmlutils.test.collection1:` updated: None WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_which_cannot_be_normalized_is_written_as_given[sbmlutils.test.collection1/] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'sbmlutils.test.collection1/' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_which2') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eb245b050> @pytest.mark.parametrize("resource", LOSSY_RESOURCES) def test_annotation_resource_which_cannot_be_normalized_is_written_as_given( resource: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource is written as given rather than as something else. An annotation is written as `RDFAnnotation.resource_normalized`, which does not exist for a resource without a term and is not a resource of identifiers.org any more for one without a collection. Writing either would make the annotation say something else than the model definition did. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:350: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_which_cannot_be_normalized_is_written_as_given[urn:miriam::bar] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam::bar' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_which3') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eb2459e50> @pytest.mark.parametrize("resource", LOSSY_RESOURCES) def test_annotation_resource_which_cannot_be_normalized_is_written_as_given( resource: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource is written as given rather than as something else. An annotation is written as `RDFAnnotation.resource_normalized`, which does not exist for a resource without a term and is not a resource of identifiers.org any more for one without a collection. Writing either would make the annotation say something else than the model definition did. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:350: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:298: in __init__ self.resource_normalized, ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:377: in resource_normalized namespace = get_registry().ns_dict.get(self.collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_of_a_known_collection_is_normalized[chebi/CHEBI:12965-https://identifiers.org/CHEBI:12965] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'chebi/CHEBI:12965', expected = 'https://identifiers.org/CHEBI:12965' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_of_a_0') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eb23e4140> @pytest.mark.parametrize(("resource", "expected"), NORMALIZED_RESOURCES) def test_annotation_resource_of_a_known_collection_is_normalized( resource: str, expected: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource which keeps its collection and term is normalized. Every one of these normalizes to an identifiers.org URL of the collection and term it was given with, so nothing is lost and no warning is due. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:406: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_of_a_known_collection_is_normalized[urn:miriam:chebi:CHEBI%3A33699-https://identifiers.org/CHEBI:33699] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:chebi:CHEBI%3A33699' expected = 'https://identifiers.org/CHEBI:33699' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_of_a_1') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eaa60d8b0> @pytest.mark.parametrize(("resource", "expected"), NORMALIZED_RESOURCES) def test_annotation_resource_of_a_known_collection_is_normalized( resource: str, expected: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource which keeps its collection and term is normalized. Every one of these normalizes to an identifiers.org URL of the collection and term it was given with, so nothing is lost and no warning is due. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:406: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_of_a_known_collection_is_normalized[http://identifiers.org/BTO:0000131-https://identifiers.org/BTO:0000131] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/BTO:0000131' expected = 'https://identifiers.org/BTO:0000131' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_of_a_2') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eaa6b43d0> @pytest.mark.parametrize(("resource", "expected"), NORMALIZED_RESOURCES) def test_annotation_resource_of_a_known_collection_is_normalized( resource: str, expected: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource which keeps its collection and term is normalized. Every one of these normalizes to an identifiers.org URL of the collection and term it was given with, so nothing is lost and no warning is due. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:406: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_of_a_known_collection_is_normalized[UO:0000021-https://identifiers.org/UO:0000021] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'UO:0000021', expected = 'https://identifiers.org/UO:0000021' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_of_a_3') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eaa683930> @pytest.mark.parametrize(("resource", "expected"), NORMALIZED_RESOURCES) def test_annotation_resource_of_a_known_collection_is_normalized( resource: str, expected: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource which keeps its collection and term is normalized. Every one of these normalizes to an identifiers.org URL of the collection and term it was given with, so nothing is lost and no warning is due. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:406: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_of_a_known_collection_is_normalized[http://identifiers.org/sbmlutils.test.collection1/1406-https://identifiers.org/sbmlutils.test.collection1/1406] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/sbmlutils.test.collection1/1406' expected = 'https://identifiers.org/sbmlutils.test.collection1/1406' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_of_a_4') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eb39c97e0> @pytest.mark.parametrize(("resource", "expected"), NORMALIZED_RESOURCES) def test_annotation_resource_of_a_known_collection_is_normalized( resource: str, expected: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource which keeps its collection and term is normalized. Every one of these normalizes to an identifiers.org URL of the collection and term it was given with, so nothing is lost and no warning is due. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:406: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_of_a_known_collection_is_normalized[http://identifiers.org/sbmlutils.test.collection1/XX:0000040-https://identifiers.org/sbmlutils.test.collection1/XX:0000040] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/sbmlutils.test.collection1/XX:0000040' expected = 'https://identifiers.org/sbmlutils.test.collection1/XX:0000040' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_of_a_5') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eb25c8ad0> @pytest.mark.parametrize(("resource", "expected"), NORMALIZED_RESOURCES) def test_annotation_resource_of_a_known_collection_is_normalized( resource: str, expected: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource which keeps its collection and term is normalized. Every one of these normalizes to an identifiers.org URL of the collection and term it was given with, so nothing is lost and no warning is due. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:406: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_of_a_known_collection_is_normalized[https://identifiers.org/SBMLUTILS.TEST.COLLECTION1:0000012-https://identifiers.org/SBMLUTILS.TEST.COLLECTION1:0000012] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'https://identifiers.org/SBMLUTILS.TEST.COLLECTION1:0000012' expected = 'https://identifiers.org/SBMLUTILS.TEST.COLLECTION1:0000012' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_of_a_6') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eaad9b890> @pytest.mark.parametrize(("resource", "expected"), NORMALIZED_RESOURCES) def test_annotation_resource_of_a_known_collection_is_normalized( resource: str, expected: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource which keeps its collection and term is normalized. Every one of these normalizes to an identifiers.org URL of the collection and term it was given with, so nothing is lost and no warning is due. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:406: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_of_a_known_collection_is_normalized[http://identifiers.org/chebi/000000035-https://identifiers.org/chebi/000000035] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/chebi/000000035' expected = 'https://identifiers.org/chebi/000000035' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_of_a_7') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eab075de0> @pytest.mark.parametrize(("resource", "expected"), NORMALIZED_RESOURCES) def test_annotation_resource_of_a_known_collection_is_normalized( resource: str, expected: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource which keeps its collection and term is normalized. Every one of these normalizes to an identifiers.org URL of the collection and term it was given with, so nothing is lost and no warning is due. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:406: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_annotation_resource_of_a_known_collection_is_normalized[urn:miriam:sbmlutils.test.collection1:bar-https://identifiers.org/sbmlutils.test.collection1/bar] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:sbmlutils.test.collection1:bar' expected = 'https://identifiers.org/sbmlutils.test.collection1/bar' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_resource_of_a_8') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eaa70a410> @pytest.mark.parametrize(("resource", "expected"), NORMALIZED_RESOURCES) def test_annotation_resource_of_a_known_collection_is_normalized( resource: str, expected: str, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource which keeps its collection and term is normalized. Every one of these normalizes to an identifiers.org URL of the collection and term it was given with, so nothing is lost and no warning is due. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_species(resource, sbml_path) tests/metadata/test_annotator.py:406: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:289: in _annotated_species _annotated_model([resource], sbml_path) tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ___________ test_annotation_losses_are_reported_once_per_collection ____________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_losses_are_rep0') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7ea826e2b0> def test_annotation_losses_are_reported_once_per_collection( tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a document reports one warning per collection, not per resource. Writing one warning per resource buried every other message, 19853 of them for the Recon3D fixture while pymetadata up to 0.6.3 lost the collections the registry does not know, and taught users to silence the logger. The detail of each resource stays available at debug. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.DEBUG, logger="sbmlutils.metadata.annotator"): > _annotated_model(TWO_LOSSY_COLLECTIONS, sbml_path) tests/metadata/test_annotator.py:451: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING pymetadata.core.annotation:annotation.py:295 Deprecated urn pattern `urn:miriam:sbmlutils.test.collection1` updated: None WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _____________ test_annotation_losses_do_not_leak_between_documents _____________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_losses_do_not_0') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7eaa90c320> def test_annotation_losses_do_not_leak_between_documents( tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that each written document reports its own resources. The collector is installed per document. A collector kept beyond the document it was installed for would add the resources of the first document to the report of the second. """ with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_model(TWO_LOSSY_COLLECTIONS[:3], tmp_path / "first.xml") tests/metadata/test_annotator.py:482: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING pymetadata.core.annotation:annotation.py:295 Deprecated urn pattern `urn:miriam:sbmlutils.test.collection1` updated: None WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _________ test_annotation_loss_without_a_collection_is_grouped_as_such _________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_annotation_loss_without_a0') caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7e9b8359d0> def test_annotation_loss_without_a_collection_is_grouped_as_such( tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Test that a resource with an empty collection is still reported. There is no collection to group such a resource under, and dropping it from the report for that reason would hide it entirely, so all of them are reported together under a placeholder. """ sbml_path = tmp_path / "annotation.xml" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > _annotated_model(["urn:miriam::bar", "urn:miriam::baz"], sbml_path) tests/metadata/test_annotator.py:511: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/metadata/test_annotator.py:263: in _annotated_model create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:298: in __init__ self.resource_normalized, ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:377: in resource_normalized namespace = get_registry().ns_dict.get(self.collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _______ test_annotation_loss_outside_a_document_is_reported_per_resource _______ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: caplog = <_pytest.logging.LogCaptureFixture object at 0x7f7ea81429d0> def test_annotation_loss_outside_a_document_is_reported_per_resource( caplog: pytest.LogCaptureFixture, ) -> None: """Test that a single annotation written on its own reports itself. `ModelAnnotator.annotate_sbase` annotates one element at a time and is called directly. There is no document scope then, and nothing would ever report a resource which was only collected. """ doc = libsbml.SBMLDocument(3, 2) model: libsbml.Model = doc.createModel("m") compartment: libsbml.Compartment = model.createCompartment() compartment.setId("c") compartment.setConstant(True) resource = f"urn:miriam:{UNKNOWN_COLLECTION}" with caplog.at_level(logging.WARNING, logger="sbmlutils.metadata.annotator"): > ModelAnnotator.annotate_sbase(compartment, Annotation(BQB.IS, resource)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/metadata/test_annotator.py:536: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING pymetadata.core.annotation:annotation.py:295 Deprecated urn pattern `urn:miriam:sbmlutils.test.collection1` updated: None WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset __________________ test_retained_annotation_is_informational ___________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_retained_annotation_is_in0') def test_retained_annotation_is_informational(tmp_path: Path) -> None: """Strict construction accepts resources which are preserved verbatim.""" from sbmlutils.factory import Compartment, Species from sbmlutils.metadata import BQB resource = "urn:miriam::bar" model = Model( "m", compartments=[Compartment("c", 1)], species=[Species("s", "c", initialAmount=1, annotations=[(BQB.IS, resource)])], ) > result = create_model(model, tmp_path / "m.xml", strict=True, validate=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_construction_diagnostics.py:165: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:298: in __init__ self.resource_normalized, ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:377: in resource_normalized namespace = get_registry().ns_dict.get(self.collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Compartment(c)' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Species(s)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Species(s)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(s)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ___________________________ test_sabiork_uncertainty ___________________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: def test_sabiork_uncertainty() -> None: """Test SabioRK uncertainty.""" model_dict: dict[str, Any] = { "sid": "sabiork_parameter", "packages": [Package.DISTRIB_V1], "model_units": ModelUnits( time=U.hr, extent=U.mole, substance=U.mole, length=U.meter, area=U.m2, volume=U.liter, ), "units": U, "parameters": [ Parameter( sid="Km_glc", name="Michelis-Menten constant glucose", value=5.0, unit=U.mM, sboTerm=SBO.MICHAELIS_CONSTANT, uncertainties=[ Uncertainty( sid="uncertainty1", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=5.07 ), UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_STANDARDDEVIATION, value=0.97, ), ], annotations=[ (BQB.IS, "sabiork.kineticrecord/793"), # entry in SABIO-RK (BQB.HAS_TAXON, "taxonomy/9606"), # homo sapiens (BQB.IS, "ec-code/2.7.1.2"), # glucokinase (BQB.IS, "uniprot/P35557"), # Glucokinase homo sapiens (BQB.IS, "bto/BTO:0000075"), # liver ], ), Uncertainty( sid="uncertainty2", uncertParameters=[ UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_MEAN, value=2.7 ), UncertParameter( type=libsbml.DISTRIB_UNCERTTYPE_STANDARDDEVIATION, value=0.11, ), ], annotations=[ (BQB.IS, "sabiork.kineticrecord/2581"), # entry in SABIO-RK (BQB.HAS_TAXON, "taxonomy/9606"), # homo sapiens (BQB.IS, "ec-code/2.7.1.2"), # glucokinase (BQB.IS, "uniprot/P35557"), # Glucokinase homo sapiens (BQB.IS, "bto/BTO:0000075"), # liver ], ), ], ) ], } > check_model(Model(**model_dict)) tests/test_distrib.py:511: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_distrib.py:88: in check_model doc: libsbml.SBMLDocument = Document(model=model).create_sbml() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:797: in create_sbml self._set_fields(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Uncertainty(uncertainty1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Uncertainty(uncertainty1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(Km_glc, Michelis-Menten constant glucose, SBO_0000027, [Uncertainty(uncertainty1, UncertParameter(4, 5.07 [None]), UncertParameter(9, 0.97 [None])), Uncertainty(uncertainty2, UncertParameter(4, 2.7 [None]), UncertParameter(9, 0.11 [None]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) __________________ test_reaction_modifier_keeps_sbase_fields ___________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: def test_reaction_modifier_keeps_sbase_fields() -> None: """Test that a modifier's metaId, sboTerm, name, notes and annotation survive. The writer of a species reference used to only set `species`, `sid`, `constant`, `stoichiometry`, `metaId` and `sboTerm`; `name`, `notes` and `annotations` were silently dropped, for reactants, products and modifiers alike. This asserts against the actual created `libsbml.ModifierSpeciesReference`, not against the python `EquationPart` it was built from, so it fails if `_SpeciesReference` stops writing any of these. """ _doc, model = _reaction_test_model() equation = ReactionEquation( reactants=[EquationPart(species="A")], products=[EquationPart(species="B")], modifiers=[ EquationPart( species="M", metaId="mod1", sboTerm="SBO:0000019", name="modifiername", notes="a modifier", annotations=[(BQB.IS, "uniprot/P35557")], ) ], ) reaction = Reaction("r1", equation) > reaction.create_sbml(model) tests/test_factory.py:1633: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:1440: in create_sbml _SpeciesReference(modifier)._set_fields(r.createModifier(), model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:1256: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Reaction(r1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Reaction(r1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ___________ test_reaction_reactant_keeps_name_notes_and_annotations ____________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: def test_reaction_reactant_keeps_name_notes_and_annotations() -> None: """Test that a reactant's name, notes and annotation survive, not only its metadata. Only `metaId`/`sboTerm`/`constant`/`stoichiometry` were set on a `SpeciesReference` before this task; `name`, `notes` and `annotations` were dropped for reactants and products exactly like for modifiers. """ _doc, model = _reaction_test_model() equation = ReactionEquation( reactants=[ EquationPart( species="A", name="reactantname", notes="a reactant", annotations=[(BQB.IS, "uniprot/P35557")], ) ], products=[EquationPart(species="B")], ) reaction = Reaction("r1", equation) > reaction.create_sbml(model) tests/test_factory.py:1664: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:1434: in create_sbml _SpeciesReference(reactant)._set_fields(r.createReactant(), model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:1256: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Reaction(r1)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Reaction(r1)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_an_annotation_which_is_neither_an_annotation_nor_a_tuple_raises[second] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_an_annotation_which_is_ne1') annotations = [(, 'chebi/CHEBI:15422'), 'chebi/CHEBI:15422'] @pytest.mark.parametrize( "annotations", [ pytest.param(["chebi/CHEBI:15422"], id="first"), pytest.param([(BQB.IS, "chebi/CHEBI:15422"), "chebi/CHEBI:15422"], id="second"), ], ) def test_an_annotation_which_is_neither_an_annotation_nor_a_tuple_raises( tmp_path: Path, annotations: list[Any] ) -> None: """An annotation entry of an unsupported type raises instead of failing late. As the first entry it raised an `UnboundLocalError`, after another entry it silently duplicated the annotation before it. """ model = Model( "m", parameters=[Parameter("p", 1.0, annotations=annotations)], ) with pytest.raises(ValueError, match="chebi/CHEBI:15422"): > create_model(model, filepath=tmp_path / "model.xml", validate=False) tests/test_factory.py:3564: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(p)' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(p)' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ________________ test_roundtrip_document_returns_both_documents ________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_roundtrip_document_return0') def test_roundtrip_document_returns_both_documents(tmp_path: Path) -> None: """Test that a round trip returns the document read and the one written.""" > doc_in, doc_out = roundtrip_document(UNCERTAINTY_SBML, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:953: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:797: in create_sbml self._set_fields(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(UncertParameter(4, 5.0 [mole]), UncertParameter(9, 0.3 [mole]), UncertSpan(15, 2.0 - 8.0 [mole])), Uncertainty(UncertParameter(2, 0.0 [mole]), UncertParameter(3, 1.0 [mole]), UncertParameter(4, 2.0 [mole]), UncertParameter(5, 3.0 [mole]), UncertParameter(6, 4.0 [mole]), UncertParameter(7, 5.0 [mole]), UncertParameter(8, 6.0 [mole]), UncertParameter(9, 7.0 [mole]), UncertParameter(10, 8.0 [mole]), UncertParameter(11, 9.0 [mole])), Uncertainty(UncertSpan(12, -1.0 - 1.0 [mole]), UncertSpan(13, 0.0 - 2.0 [mole]), UncertSpan(14, 1.0 - 3.0 [mole]), UncertSpan(15, 2.0 - 4.0 [mole])), Uncertainty(UncertParameter(0, None [None])), Uncertainty(UncertParameter(1, 0.25 [mole])), Uncertainty(UncertParameter(0, None [mole]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _____________________ test_roundtrip_preserves_fbc_strict ______________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_roundtrip_preserves_fbc_s0') def test_roundtrip_preserves_fbc_strict(tmp_path: Path) -> None: """Test that `fbc:strict="true"` of the source survives the round trip. `FBC_ECOLI_CORE_SBML` declares `fbc:strict="true"`. `Document.create_sbml` used to hardcode `setStrict(False)`, which lost it on every round trip. This asserts on `fbc.strict` alone, never on an empty diff: what the rest of the fixture round trips is the subject of the sweep, and one construct which starts to differ must not turn this test red for something it is not about. """ > doc_in, doc_out = roundtrip_document(FBC_ECOLI_CORE_SBML, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:971: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(M_glc__D_e, D-Glucose, SBO:0000247, M_glc__D_e)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ____________________ test_roundtrip_preserves_gene_products ____________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7f7ea8151850> def test_roundtrip_preserves_gene_products( package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that the gene products of a model and its associations survive a round trip. `FBC_ECOLI_CORE_SBML` has 137 gene products, every one of them annotated, and 69 reactions with a gene product association. """ > counts, _ = package_roundtrip(FBC_ECOLI_CORE_SBML) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:1128: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(M_glc__D_e, D-Glucose, SBO:0000247, M_glc__D_e)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_roundtrip_loses_only_the_sboterm_of_an_association_node[e_coli_core.xml] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: sbml_path = PosixPath('/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/resources/distrib/e_coli_core.xml') tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_roundtrip_loses_only_the_0') @pytest.mark.parametrize( "sbml_path", [ECOLI_CORE_DISTRIB_SBML, ECOLI_EXPRESSION_SBML], ids=fixture_idfn, ) def test_roundtrip_loses_only_the_sboterm_of_an_association_node( sbml_path: Path, tmp_path: Path ) -> None: """Test that a round trip loses no more of an association than the sboTerm of a node. `Reaction.geneProductAssociation` holds an association as the infix string of its gene product ids, and a string cannot hold what a node of the association carries: `tests/structural.py` therefore compares the metadata of every `and`, `or` and `geneProductRef` node as `nodes`, apart from the string. The two e_coli_core fixtures of `resources/distrib` are the only documents of the corpus whose nodes carry any, and this is the loss that is left; it is not whitelisted, it is pinned here. What is lost has to stay exactly this: an `sboTerm` on an `and` or an `or` node which restates the operator of that node, so the infix string loses nothing which is not derivable from it. Any other metadata on a node - a metaid, an annotation, notes, another term, or anything at all on a `geneProductRef` - would be a real loss and fails this test, and so does a changed association string, which is asserted literally rather than left to the whitelist. """ > doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:1172: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_roundtrip_loses_only_the_sboterm_of_an_association_node[e_coli_core_expression.xml] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: sbml_path = PosixPath('/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/resources/distrib/e_coli_core_expression.xml') tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_roundtrip_loses_only_the_1') @pytest.mark.parametrize( "sbml_path", [ECOLI_CORE_DISTRIB_SBML, ECOLI_EXPRESSION_SBML], ids=fixture_idfn, ) def test_roundtrip_loses_only_the_sboterm_of_an_association_node( sbml_path: Path, tmp_path: Path ) -> None: """Test that a round trip loses no more of an association than the sboTerm of a node. `Reaction.geneProductAssociation` holds an association as the infix string of its gene product ids, and a string cannot hold what a node of the association carries: `tests/structural.py` therefore compares the metadata of every `and`, `or` and `geneProductRef` node as `nodes`, apart from the string. The two e_coli_core fixtures of `resources/distrib` are the only documents of the corpus whose nodes carry any, and this is the loss that is left; it is not whitelisted, it is pinned here. What is lost has to stay exactly this: an `sboTerm` on an `and` or an `or` node which restates the operator of that node, so the infix string loses nothing which is not derivable from it. Any other metadata on a node - a metaid, an annotation, notes, another term, or anything at all on a `geneProductRef` - would be a real loss and fails this test, and so does a changed association string, which is asserted literally rather than left to the whitelist. """ > doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:1172: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _____________________ test_roundtrip_preserves_objectives ______________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7f7ea8151850> def test_roundtrip_preserves_objectives( package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that the objective of a model and its flux objectives survive a round trip. `FBC_ECOLI_CORE_SBML` maximizes the biomass reaction, which is the one thing an FBA model is run for. """ > counts, _ = package_roundtrip(FBC_ECOLI_CORE_SBML) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:1206: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(M_glc__D_e, D-Glucose, SBO:0000247, M_glc__D_e)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ______________ test_roundtrip_preserves_bounds_charge_and_formula ______________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7f7ea8151850> def test_roundtrip_preserves_bounds_charge_and_formula( package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that the flux bounds, charges and chemical formulas of a model survive. The flux bounds of `FBC_ECOLI_CORE_SBML` are what makes its flux space finite; 72 of its 72 species carry a charge and a chemical formula. """ > counts, _ = package_roundtrip(FBC_ECOLI_CORE_SBML) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:1272: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(M_glc__D_e, D-Glucose, SBO:0000247, M_glc__D_e)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ______ test_roundtrip_preserves_the_whole_fbc_content[e_coli_core.xml.gz] ______ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: sbml_path = PosixPath('/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/resources/models/fbc/e_coli_core.xml.gz') constructs = ('fbc.package', 'fbc.strict', 'fbc.geneProduct', 'fbc.geneProductAssociation', 'fbc.fluxBound', 'fbc.charge', ...) package_roundtrip = .compare at 0x7f7ea8151850> @pytest.mark.parametrize( ("sbml_path", "constructs"), [ # the round trip of Recon3D takes about 25 s, a third of the test run pytest.param( sbml_path, constructs, id=sbml_path.name, marks=[pytest.mark.slow] if sbml_path == FBC_RECON3D_SBML else [], ) for sbml_path, constructs in FBC_FIXTURES ], ) def test_roundtrip_preserves_the_whole_fbc_content( sbml_path: Path, constructs: tuple[str, ...], package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that a round trip of an fbc fixture changes no fbc content at all. Between them the three fixtures carry every fbc construct the parser reads: `FBC_RECON3D_SBML` is the largest model of the repository with 2248 gene products, 10600 flux bounds and 5835 charges, and `FBC_UDC_SBML` is the only one with user-defined constraints. This asserts on every fbc difference, not on the named constructs only, so an fbc construct the round trip *adds* fails it too. """ > counts, differences = package_roundtrip(sbml_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:1837: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(M_glc__D_e, D-Glucose, SBO:0000247, M_glc__D_e)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ________ test_roundtrip_preserves_the_whole_fbc_content[Recon3D.xml.gz] ________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: sbml_path = PosixPath('/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/resources/models/fbc/Recon3D.xml.gz') constructs = ('fbc.package', 'fbc.strict', 'fbc.geneProduct', 'fbc.geneProductAssociation', 'fbc.fluxBound', 'fbc.charge', ...) package_roundtrip = .compare at 0x7f7ea8151850> @pytest.mark.parametrize( ("sbml_path", "constructs"), [ # the round trip of Recon3D takes about 25 s, a third of the test run pytest.param( sbml_path, constructs, id=sbml_path.name, marks=[pytest.mark.slow] if sbml_path == FBC_RECON3D_SBML else [], ) for sbml_path, constructs in FBC_FIXTURES ], ) def test_roundtrip_preserves_the_whole_fbc_content( sbml_path: Path, constructs: tuple[str, ...], package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that a round trip of an fbc fixture changes no fbc content at all. Between them the three fixtures carry every fbc construct the parser reads: `FBC_RECON3D_SBML` is the largest model of the repository with 2248 gene products, 10600 flux bounds and 5835 charges, and `FBC_UDC_SBML` is the only one with user-defined constraints. This asserts on every fbc difference, not on the named constructs only, so an fbc construct the round trip *adds* fails it too. """ > counts, differences = package_roundtrip(sbml_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:1837: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(M_10fthf_c, 10-Formyltetrahydrofolate, SBO:0000247, M_10fthf_c)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _________ test_roundtrip_flattens_exactly_the_two_pinned_associations __________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_roundtrip_flattens_exactl0') def test_roundtrip_flattens_exactly_the_two_pinned_associations( tmp_path: Path, ) -> None: """Test that the whitelist hides the flattening of a real round trip and nothing else. `gpa-flattening` is the one whitelist entry the fbc round trip relies on, and `R_PFL` and `R_ATPS4r` of `FBC_ECOLI_CORE_SBML` are the only two associations of that fixture it applies to, see `test_gpa_flattening_pins_every_association_libsbml_changes`. Both forms are spelled out here, so a round trip which changes an association in any other way fails this even where the entry would accept it; the entry itself is held to the two strings as well. The entry hides that flattening and nothing more, which the synthetic change at the end shows: one gene of the association written back is replaced, and the comparison reports exactly that reaction. """ > doc_in, doc_out = roundtrip_document(FBC_ECOLI_CORE_SBML, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2000: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Species(M_glc__D_e, D-Glucose, SBO:0000247, M_glc__D_e)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_identifiers_org_is_what_pymetadata_does[urn:miriam:chebi:CHEBI%3A33699] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:chebi:CHEBI%3A33699' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ___ test_identifiers_org_is_what_pymetadata_does[urn:miriam:uniprot:P03023] ____ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:uniprot:P03023' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[urn:miriam:obo.go:GO%3A0005623] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:obo.go:GO%3A0005623' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[urn:miriam:biomodels.sbo:SBO%3A0000247] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:biomodels.sbo:SBO%3A0000247' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[urn:miriam:kegg.compound:C00031] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:kegg.compound:C00031' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ____ test_identifiers_org_is_what_pymetadata_does[urn:miriam:taxonomy:9606] ____ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:taxonomy:9606' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ___ test_identifiers_org_is_what_pymetadata_does[urn:miriam:pubmed:10643997] ___ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:pubmed:10643997' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ___ test_identifiers_org_is_what_pymetadata_does[urn:miriam:ec-code:1.1.1.1] ___ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:ec-code:1.1.1.1' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[urn:miriam:reactome:REACT_1234] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:reactome:REACT_1234' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[urn:miriam:sbmlutils.test.collection1:bar] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:sbmlutils.test.collection1:bar' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[urn:miriam:sbmlutils.test.collection1:BAR%3A123] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'urn:miriam:sbmlutils.test.collection1:BAR%3A123' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/chebi/CHEBI:12965] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/chebi/CHEBI:12965' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/uniprot/P03023] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/uniprot/P03023' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/go/GO:0005623] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/go/GO:0005623' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/obo.go/GO:0005623] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/obo.go/GO:0005623' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/biomodels.sbo/SBO:0000247] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/biomodels.sbo/SBO:0000247' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/kegg.compound/C00031] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/kegg.compound/C00031' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/pubmed/10643997] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/pubmed/10643997' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/bigg.metabolite/glc__D] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/bigg.metabolite/glc__D' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/asap/ABE-0000027] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/asap/ABE-0000027' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[https://identifiers.org/taxonomy/9606] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'https://identifiers.org/taxonomy/9606' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/ec-code/1.1.1.1] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/ec-code/1.1.1.1' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/yaaK] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/refseq_synonym/yaaK' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/sbmlutils.test.collection1/1406] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/sbmlutils.test.collection1/1406' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/sbmlutils.test.collection1/XX:0000040] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/sbmlutils.test.collection1/XX:0000040' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/chebi/000000035] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/chebi/000000035' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/BTO:0000131] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/BTO:0000131' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/SBO:0000625] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/SBO:0000625' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/FMA:12274] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/FMA:12274' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/CHEBI:33699] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/CHEBI:33699' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/GO:0005623] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/GO:0005623' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/uniprot:P03023] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/uniprot:P03023' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/kegg.compound:C00031] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/kegg.compound:C00031' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ___________ test_identifiers_org_is_what_pymetadata_does[UO:0000021] ___________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'UO:0000021' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset __________ test_identifiers_org_is_what_pymetadata_does[CHEBI:33699] ___________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'CHEBI:33699' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ___________ test_identifiers_org_is_what_pymetadata_does[GO:0005623] ___________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'GO:0005623' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset __________ test_identifiers_org_is_what_pymetadata_does[SBO:0000247] ___________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'SBO:0000247' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _________ test_identifiers_org_is_what_pymetadata_does[uniprot:P03023] _________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'uniprot:P03023' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/iex?] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/refseq_synonym/iex?' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/iex?a=b] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/refseq_synonym/iex?a=b' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/iex#fragment] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/refseq_synonym/iex#fragment' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/iex/] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/refseq_synonym/iex/' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/iex?#] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/refseq_synonym/iex?#' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/chebi/CHEBI:12965/?a=b#c] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/chebi/CHEBI:12965/?a=b#c' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[https://identifiers.org/uniprot/P03023?] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'https://identifiers.org/uniprot/P03023?' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/BTO:0000131?] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/BTO:0000131?' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/BTO:0000131/] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/BTO:0000131/' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/uniprot:P03023?a=b#c] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/uniprot:P03023?a=b#c' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/sbmlutils.test.collection1/1406?] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: resource = 'http://identifiers.org/sbmlutils.test.collection1/1406?' @pytest.mark.parametrize( "resource", [*_URNS, *_CLASSIC_URLS, *_COMPACT_URLS, *_BARE_IDENTIFIERS, *_DECORATED_URLS], ) def test_identifiers_org_is_what_pymetadata_does(resource: str) -> None: """Test the normalization against the canonicalization of pymetadata. `create_model` writes a resource as pymetadata normalizes it whenever the normalization keeps the collection and the term of the resource, and as given when it does not, see `_resource_for_cvterm` of `sbmlutils.metadata.annotator`. Whenever it does normalize, it writes exactly what pymetadata writes, so the whitelist entry has to accept that for each of the four source forms: a MIRIAM URN, a classic identifiers.org URL, the `http` spelling of the compact URL and a bare compact identifier. The expectation is measured, never spelled out here. This is about the whitelist entry, not about which resources are written that way, which is `tests/metadata/test_annotator.py`. """ > url = RDFAnnotation(BQB.IS, resource, validate=False).resource_normalized ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _____ test_roundtrip_preserves_the_whole_distrib_content[uncertainty.xml] ______ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: sbml_path = PosixPath('/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/resources/distrib/uncertainty.xml') constructs = ('distrib.package', 'distrib.uncertainty', 'distrib.uncertParameter') package_roundtrip = .compare at 0x7f7ea8151850> @pytest.mark.parametrize( ("sbml_path", "constructs"), DISTRIB_FIXTURES, ids=[sbml_path.name for sbml_path, _ in DISTRIB_FIXTURES], ) def test_roundtrip_preserves_the_whole_distrib_content( sbml_path: Path, constructs: tuple[str, ...], package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that a round trip of a distrib fixture changes no distrib content at all. Between them the fixtures carry every distrib construct: `UNCERTAINTY_SBML` has six uncertainties with every type of uncert parameter and span, a definitionURL, math and a nested `listOfUncertParameters`, `ECOLI_EXPRESSION_SBML` has one on a gene product, `MODEL_SBML` one on a compartment, and the three files of distributions use the csymbols of distrib in the math of core elements. Each is asserted to have the constructs first, so preserving them cannot mean that the fixture has none, and every difference is asserted, not only the ones of the named constructs, so a distrib construct the round trip *adds* fails it too. `DISTRIB_COMP_SBML` is missing from the list on purpose: it is the same model as `DISTRIB_COMP_FLAT_SBML` with a comp port, and it is asserted with both of its packages in `test_roundtrip_of_a_distrib_comp_model_keeps_both_packages`. """ > counts, differences = package_roundtrip(sbml_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2634: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/distrib.py:797: in create_sbml self._set_fields(uncertainty, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(p1, [Uncertainty(UncertParameter(4, 5.0 [mole]), UncertParameter(9, 0.3 [mole]), UncertSpan(15, 2.0 - 8.0 [mole])), Uncertainty(UncertParameter(2, 0.0 [mole]), UncertParameter(3, 1.0 [mole]), UncertParameter(4, 2.0 [mole]), UncertParameter(5, 3.0 [mole]), UncertParameter(6, 4.0 [mole]), UncertParameter(7, 5.0 [mole]), UncertParameter(8, 6.0 [mole]), UncertParameter(9, 7.0 [mole]), UncertParameter(10, 8.0 [mole]), UncertParameter(11, 9.0 [mole])), Uncertainty(UncertSpan(12, -1.0 - 1.0 [mole]), UncertSpan(13, 0.0 - 2.0 [mole]), UncertSpan(14, 1.0 - 3.0 [mole]), UncertSpan(15, 2.0 - 4.0 [mole])), Uncertainty(UncertParameter(0, None [None])), Uncertainty(UncertParameter(1, 0.25 [mole])), Uncertainty(UncertParameter(0, None [mole]))])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _ test_roundtrip_preserves_the_whole_distrib_content[e_coli_core_expression.xml] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: sbml_path = PosixPath('/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/resources/distrib/e_coli_core_expression.xml') constructs = ('distrib.package', 'distrib.uncertainty', 'distrib.uncertParameter') package_roundtrip = .compare at 0x7f7ea8151850> @pytest.mark.parametrize( ("sbml_path", "constructs"), DISTRIB_FIXTURES, ids=[sbml_path.name for sbml_path, _ in DISTRIB_FIXTURES], ) def test_roundtrip_preserves_the_whole_distrib_content( sbml_path: Path, constructs: tuple[str, ...], package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that a round trip of a distrib fixture changes no distrib content at all. Between them the fixtures carry every distrib construct: `UNCERTAINTY_SBML` has six uncertainties with every type of uncert parameter and span, a definitionURL, math and a nested `listOfUncertParameters`, `ECOLI_EXPRESSION_SBML` has one on a gene product, `MODEL_SBML` one on a compartment, and the three files of distributions use the csymbols of distrib in the math of core elements. Each is asserted to have the constructs first, so preserving them cannot mean that the fixture has none, and every difference is asserted, not only the ones of the named constructs, so a distrib construct the round trip *adds* fails it too. `DISTRIB_COMP_SBML` is missing from the list on purpose: it is the same model as `DISTRIB_COMP_FLAT_SBML` with a comp port, and it is asserted with both of its packages in `test_roundtrip_of_a_distrib_comp_model_keeps_both_packages`. """ > counts, differences = package_roundtrip(sbml_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2634: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ________ test_roundtrip_preserves_the_whole_distrib_content[model.xml] _________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: sbml_path = PosixPath('/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/resources/examples/model.xml') constructs = ('distrib.package', 'distrib.uncertainty', 'distrib.uncertParameter') package_roundtrip = .compare at 0x7f7ea8151850> @pytest.mark.parametrize( ("sbml_path", "constructs"), DISTRIB_FIXTURES, ids=[sbml_path.name for sbml_path, _ in DISTRIB_FIXTURES], ) def test_roundtrip_preserves_the_whole_distrib_content( sbml_path: Path, constructs: tuple[str, ...], package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that a round trip of a distrib fixture changes no distrib content at all. Between them the fixtures carry every distrib construct: `UNCERTAINTY_SBML` has six uncertainties with every type of uncert parameter and span, a definitionURL, math and a nested `listOfUncertParameters`, `ECOLI_EXPRESSION_SBML` has one on a gene product, `MODEL_SBML` one on a compartment, and the three files of distributions use the csymbols of distrib in the math of core elements. Each is asserted to have the constructs first, so preserving them cannot mean that the fixture has none, and every difference is asserted, not only the ones of the named constructs, so a distrib construct the round trip *adds* fails it too. `DISTRIB_COMP_SBML` is missing from the list on purpose: it is the same model as `DISTRIB_COMP_FLAT_SBML` with a comp port, and it is asserted with both of its packages in `test_roundtrip_of_a_distrib_comp_model_keeps_both_packages`. """ > counts, differences = package_roundtrip(sbml_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2634: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(k1, SBO:0000009, meta_k1)' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) ______________ test_roundtrip_preserves_the_submodels_of_icg_body ______________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7f7ea8151850> def test_roundtrip_preserves_the_submodels_of_icg_body( package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that the submodel of `COMP_ICG_BODY` survives a round trip. The model is a whole-body PBPK model whose liver is a submodel of an external model definition, so it has exactly one ``, with an id and a name. """ > comparison = package_roundtrip(COMP_ICG_BODY) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2857: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ________________ test_roundtrip_preserves_the_ports_of_icg_body ________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7f7ea8151850> def test_roundtrip_preserves_the_ports_of_icg_body( package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that the 16 ports of `COMP_ICG_BODY` survive a round trip. Every port has an id, a name, a metaid and an sboTerm of its own, and each references a parameter or a species of the model by `idRef`. """ > comparison = package_roundtrip(COMP_ICG_BODY) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2884: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _________________ test_roundtrip_writes_each_port_exactly_once _________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_roundtrip_writes_each_por0') def test_roundtrip_writes_each_port_exactly_once(tmp_path: Path) -> None: """Test that a port read is written once, not once per way of writing it. `sbmlutils.factory` writes a port from the `ports` of the model and from the `port=True`/`port=Port(...)` shorthand of the element it references, and an element which carried both would be given two ports. The parser reads a port into the `ports` of the model only: the list keeps the port's own id, name, metaid, sboTerm and order, and it does not depend on the referenced element accepting a `port=` keyword, which many do not. """ > doc_in, doc_out = roundtrip_document(COMP_ICG_BODY, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:2895: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _____________ test_roundtrip_preserves_external_model_definitions ______________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7f7ea8151850> def test_roundtrip_preserves_external_model_definitions( package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that a `` survives with its attributes. `COMP_ICG_BODY` names its liver model in a file of its own, `MINIMAL_MODEL_COMP_SBML` names five, and the comparison compares `source`, `modelRef` and `md5` of each, with its metadata. """ for sbml_path, count in [(COMP_ICG_BODY, 1), (MINIMAL_MODEL_COMP_SBML, 5)]: > comparison = package_roundtrip(sbml_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:3329: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ____________ test_roundtrip_preserves_the_comp_content_of_icg_body _____________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7f7ea8151850> def test_roundtrip_preserves_the_comp_content_of_icg_body( package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that the whole comp content of `COMP_ICG_BODY` survives a round trip. The model is a whole-body PBPK model whose liver is a submodel of an external model definition: one submodel, 16 ports, six replaced elements and one external model definition, which is every comp construct this fixture has. Each is asserted to be in the document first, so preserving them cannot mean that the fixture has none, and every comp difference is asserted, not only those of the named constructs, so comp content the round trip *adds* fails it too. """ > counts, differences = package_roundtrip(COMP_ICG_BODY) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:3442: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _____________ test_roundtrip_of_a_flat_model_gains_no_comp_content _____________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7f7ea8151850> def test_roundtrip_of_a_flat_model_gains_no_comp_content( package_roundtrip: Callable[[Path], Comparison], ) -> None: """Test that a model without comp does not gain comp content. `COMP_ICG_BODY_FLAT` is `COMP_ICG_BODY` with its submodel resolved into it: it declares no comp package and has no comp element at all, and the round trip of it must write none either. """ > counts, differences = package_roundtrip(COMP_ICG_BODY_FLAT) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:3458: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:1096: in compare doc_in, doc_out = roundtrip_document(sbml_path, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/structural.py:626: in roundtrip_document create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ______ test_roundtrip_of_an_l3v1_comp_model_validates_at_its_own_version _______ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_roundtrip_of_an_l3v1_comp0') def test_roundtrip_of_an_l3v1_comp_model_validates_at_its_own_version( tmp_path: Path, ) -> None: """Test what libsbml makes of an external model definition of another version. `COMP_ICG_BODY` is an L3V1 document whose liver submodel is the L3V1 file `icg_liver.xml` next to it. Written at L3V1, with that file beside it, the round trip validates without an error. Written at L3V2, libsbml refuses to resolve the reference, error 1020304 (`External models must be L3`, whose message says the document found at the source "was not SBML Level 3 Version 1"), and the submodel which names it is then unresolvable as well, error 1020615 (and the flattening fails, error 1090104): libsbml requires the referenced document at the level and version of the document which references it. The round trip preserves the reference and does not touch the file it names, so the level of the document written is what decides this, and a caller who needs the reference to resolve writes the level of the source. """ shutil.copy(COMP_ICG_BODY.parent / "icg_liver.xml", tmp_path / "icg_liver.xml") model = sbml_to_model(COMP_ICG_BODY) errors: dict[int, list[int]] = {} for version in (1, 2): out = tmp_path / f"icg_body-l3v{version}.xml" > create_model( model=model, filepath=out, sbml_level=3, sbml_version=version, validate=False, ) tests/test_package_roundtrip.py:3555: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _____________ test_key_value_pair_writes_every_field_it_can_carry ______________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_key_value_pair_writes_eve0') def test_key_value_pair_writes_every_field_it_can_carry(tmp_path: Path) -> None: """Test that the metadata of a key-value pair is written, not only its key.""" > sbml_path = _key_value_pair_metadata_sbml(tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:3657: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:3632: in _key_value_pair_metadata_sbml create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1141: in _set_fields self.create_key_value_pairs(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1451: in create_key_value_pairs return KeyValuePair.create_pairs(self.keyValuePairs, sbase, model, self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1605: in create_pairs return [pair.create_sbml(sbase, model) for pair in pairs] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1633: in create_sbml self._set_fields(kvp, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(k, [KeyValuePair(kind = test)])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(k, [KeyValuePair(kind = test)])' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(k, [KeyValuePair(kind = test)])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) __________ test_roundtrip_preserves_the_metadata_of_a_key_value_pair ___________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_roundtrip_preserves_the_m0') def test_roundtrip_preserves_the_metadata_of_a_key_value_pair(tmp_path: Path) -> None: """Test that the whole key-value pair survives a round trip. `structural_diff` compares the `key`, `value` and `uri` of a pair and the metadata of every element which has its own, so it sees each of the six fields. """ > sbml_path = _key_value_pair_metadata_sbml(tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_roundtrip.py:3689: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_roundtrip.py:3632: in _key_value_pair_metadata_sbml create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1141: in _set_fields self.create_key_value_pairs(sbase, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1451: in create_key_value_pairs return KeyValuePair.create_pairs(self.keyValuePairs, sbase, model, self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1605: in create_pairs return [pair.create_sbml(sbase, model) for pair in pairs] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1633: in create_sbml self._set_fields(kvp, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Model' WARNING sbmlutils.factory._core:_core.py:1112 'name' should be set on 'Parameter(k, [KeyValuePair(kind = test)])' WARNING sbmlutils.factory._core:_core.py:1117 'sboTerm' should be set on 'Parameter(k, [KeyValuePair(kind = test)])' WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset ERROR sbmlutils.factory._core:_core.py:90 Error creating SBML object for 'Parameter(k, [KeyValuePair(kind = test)])' ERROR sbmlutils.factory._core:_core.py:91 Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) _______________________ test_comp_semantics_of_icg_body ________________________ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_comp_semantics_of_icg_bod0') @requires_roadrunner def test_comp_semantics_of_icg_body(tmp_path: Path) -> None: """Test that the round trip of `COMP_ICG_BODY` flattens and simulates like the original. The model is a whole-body PBPK model whose liver is a submodel of an external model definition, the one model of the repository with a `comp:source` to another file. The flattened original is asserted to hold the content of that submodel first, so that an agreement cannot mean that nothing was resolved. """ assert [source.name for source in external_sources(COMP_ICG_BODY)] == [ "icg_liver.xml" ] > roundtrip_path = roundtrip_comp_document(COMP_ICG_BODY, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_semantics.py:424: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_semantics.py:161: in roundtrip_comp_document return roundtrip_file(sbml_path, out_dir, doc.getLevel(), doc.getVersion()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_semantics.py:124: in roundtrip_file create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _____ test_comp_semantic_diff_sees_a_damaged_round_trip[drop the submodel] _____ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: damage = expected = 'the round trip does not flatten' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_comp_semantic_diff_sees_a0') @requires_roadrunner @pytest.mark.parametrize( ("damage", "expected"), [(damage, expected) for _, damage, expected in COMP_DAMAGES], ids=[name for name, _, _ in COMP_DAMAGES], ) def test_comp_semantic_diff_sees_a_damaged_round_trip( damage: Callable[[libsbml.SBMLDocument], None], expected: str, tmp_path: Path ) -> None: """Test that the comparison of layer 2 reports a damaged round trip. A comparison which reports nothing on a damaged document verifies nothing, so each damage is applied to the round trip of `COMP_ICG_BODY`, which the comparison reports as unchanged undamaged, see `test_comp_semantics_of_icg_body`. Dropping the submodel leaves the six replaced elements referring to a submodel which is not there, which libsbml refuses to flatten; dropping a replaced element leaves the liver with its own value, which changes the flat model. """ > roundtrip_path = roundtrip_comp_document(COMP_ICG_BODY, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_semantics.py:540: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_semantics.py:161: in roundtrip_comp_document return roundtrip_file(sbml_path, out_dir, doc.getLevel(), doc.getVersion()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_semantics.py:124: in roundtrip_file create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_comp_semantic_diff_sees_a_damaged_round_trip[drop the replaced element of the liver plasma volume] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: damage = .damage at 0x7f7eaa8f1e80> expected = "differs in selection 'LI__bil_ext'" tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_comp_semantic_diff_sees_a1') @requires_roadrunner @pytest.mark.parametrize( ("damage", "expected"), [(damage, expected) for _, damage, expected in COMP_DAMAGES], ids=[name for name, _, _ in COMP_DAMAGES], ) def test_comp_semantic_diff_sees_a_damaged_round_trip( damage: Callable[[libsbml.SBMLDocument], None], expected: str, tmp_path: Path ) -> None: """Test that the comparison of layer 2 reports a damaged round trip. A comparison which reports nothing on a damaged document verifies nothing, so each damage is applied to the round trip of `COMP_ICG_BODY`, which the comparison reports as unchanged undamaged, see `test_comp_semantics_of_icg_body`. Dropping the submodel leaves the six replaced elements referring to a submodel which is not there, which libsbml refuses to flatten; dropping a replaced element leaves the liver with its own value, which changes the flat model. """ > roundtrip_path = roundtrip_comp_document(COMP_ICG_BODY, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_semantics.py:540: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_semantics.py:161: in roundtrip_comp_document return roundtrip_file(sbml_path, out_dir, doc.getLevel(), doc.getVersion()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_semantics.py:124: in roundtrip_file create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset _ test_comp_semantic_diff_sees_a_damaged_round_trip[drop the replaced element of the liver plasma concentration] _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /usr/lib/python3.15/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/util/connection.py:60: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.api.identifiers.org', port = 443 family = , type = proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib64/python3.15/socket.py:998: gaierror The above exception was the direct cause of the following exception: self = method = 'GET', url = '/resolutionApi/getResolverDataset', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=None, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=30, read=30, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.15/site-packages/urllib3/connection.py:827: in connect self.sock = sock = self._new_conn() ^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: > raise NameResolutionError(self.host, self, e) from e E urllib3.exceptions.NameResolutionError: HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution) /usr/lib/python3.15/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.15/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.15/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=None, redirect=None, status=None) method = 'GET', url = '/resolutionApi/getResolverDataset', response = None error = NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)") _pool = _stacktrace = def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/urllib3/util/retry.py:555: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: > response = get_session().get(url, params=params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.15/site-packages/requests/sessions.py:671: in get return self.request("GET", url, params=params, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = 30, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/requests/adapters.py:729: ConnectionError The above exception was the direct cause of the following exception: damage = .damage at 0x7f7eaa8f1590> expected = 'selections differ' tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_comp_semantic_diff_sees_a2') @requires_roadrunner @pytest.mark.parametrize( ("damage", "expected"), [(damage, expected) for _, damage, expected in COMP_DAMAGES], ids=[name for name, _, _ in COMP_DAMAGES], ) def test_comp_semantic_diff_sees_a_damaged_round_trip( damage: Callable[[libsbml.SBMLDocument], None], expected: str, tmp_path: Path ) -> None: """Test that the comparison of layer 2 reports a damaged round trip. A comparison which reports nothing on a damaged document verifies nothing, so each damage is applied to the round trip of `COMP_ICG_BODY`, which the comparison reports as unchanged undamaged, see `test_comp_semantics_of_icg_body`. Dropping the submodel leaves the six replaced elements referring to a submodel which is not there, which libsbml refuses to flatten; dropping a replaced element leaves the liver with its own value, which changes the flat model. """ > roundtrip_path = roundtrip_comp_document(COMP_ICG_BODY, tmp_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_semantics.py:540: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_package_semantics.py:161: in roundtrip_comp_document return roundtrip_file(sbml_path, out_dir, doc.getLevel(), doc.getVersion()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_package_semantics.py:124: in roundtrip_file create_model( ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.15/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.15/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.15/site-packages/pymetadata/webservices/registry.py:248: in update_registry namespaces = get_json(Registry.URL)["payload"]["namespaces"] ^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset' params = None def get_json(url: str, params: dict[str, str] | None = None) -> Any: """Query a url and return the parsed JSON response. Args: url: url to query params: query parameters, encoded and appended to the url Returns: The parsed JSON response. Raises: WebserviceNotFoundError: if the service answers 404 WebserviceError: if the service cannot be reached, answers with a status other than 200, or does not answer with JSON """ logger.debug("Query: %s %s", url, params or "") try: response = get_session().get(url, params=params) except requests.RequestException as err: # no network, DNS failure, timeout, too many retries, ... > raise WebserviceError(f"Service is not reachable for '{url}': {err}") from err E pymetadata.webservices.webservice.WebserviceError: Service is not reachable for 'https://registry.api.identifiers.org/resolutionApi/getResolverDataset': HTTPSConnectionPool(host='registry.api.identifiers.org', port=443): Max retries exceeded with url: /resolutionApi/getResolverDataset (Caused by NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")) /usr/lib/python3.15/site-packages/pymetadata/webservices/webservice.py:139: WebserviceError ------------------------------ Captured log call ------------------------------- WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset WARNING urllib3.connectionpool:connectionpool.py:874 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NameResolutionError("HTTPSConnection(host='registry.api.identifiers.org', port=443): Failed to resolve 'registry.api.identifiers.org' ([Errno -3] Temporary failure in name resolution)")': /resolutionApi/getResolverDataset =========================== short test summary info ============================ FAILED tests/examples/test_example_scripts.py::test_example_script[examples.converters.xpp] FAILED tests/examples/test_example_scripts.py::test_example_script[examples.distrib.distrib_packages_examples] FAILED tests/examples/test_example_scripts.py::test_example_script[examples.distrib.distrib_uncertainty] FAILED tests/examples/test_example_scripts.py::test_example_script[examples.interpolation.driving] FAILED tests/examples/test_example_scripts.py::test_example_script[examples.interpolation.interpolation] FAILED tests/examples/test_example_scripts.py::test_example_script[examples.interpolation.pancreas] FAILED tests/examples/test_example_scripts.py::test_example_script[examples.merge_models.merge_models] FAILED tests/examples/test_example_scripts.py::test_example_script[examples.tiny.simulation] FAILED tests/examples/test_examples.py::test_create_example_create[examples.tutorial.model_composition] FAILED tests/examples/test_examples.py::test_create_example_create[examples.demo.demo] FAILED tests/examples/test_examples.py::test_create_example_create[examples.tiny.tiny] FAILED tests/examples/test_examples.py::test_create_example_models[examples.annotation] FAILED tests/examples/test_examples.py::test_create_example_models[examples.fbc.fbc_v2] FAILED tests/examples/test_examples.py::test_create_example_models[examples.fbc.fbc_mass_charge] FAILED tests/examples/test_examples.py::test_create_example_models[examples.model] FAILED tests/examples/test_examples.py::test_create_example_models[examples.parameter] FAILED tests/io/test_sbml.py::test_read_sbml_reads_a_file_without_an_xml_declaration[model] FAILED tests/io/test_sbml.py::test_read_sbml_reads_a_file_without_an_xml_declaration[comp-library] FAILED tests/metadata/test_annotator.py::test_create_annotation - pymetadata.... FAILED tests/metadata/test_annotator.py::test_model_annotation - pymetadata.w... FAILED tests/metadata/test_annotator.py::test_demo_annotation - pymetadata.we... FAILED tests/metadata/test_annotator.py::test_galactose_annotation - pymetada... FAILED tests/metadata/test_annotator.py::test_annotation_resource_which_cannot_be_normalized_is_written_as_given[urn:miriam:sbmlutils.test.collection1] FAILED tests/metadata/test_annotator.py::test_annotation_resource_which_cannot_be_normalized_is_written_as_given[urn:miriam:sbmlutils.test.collection1:] FAILED tests/metadata/test_annotator.py::test_annotation_resource_which_cannot_be_normalized_is_written_as_given[sbmlutils.test.collection1/] FAILED tests/metadata/test_annotator.py::test_annotation_resource_which_cannot_be_normalized_is_written_as_given[urn:miriam::bar] FAILED tests/metadata/test_annotator.py::test_annotation_resource_of_a_known_collection_is_normalized[chebi/CHEBI:12965-https://identifiers.org/CHEBI:12965] FAILED tests/metadata/test_annotator.py::test_annotation_resource_of_a_known_collection_is_normalized[urn:miriam:chebi:CHEBI%3A33699-https://identifiers.org/CHEBI:33699] FAILED tests/metadata/test_annotator.py::test_annotation_resource_of_a_known_collection_is_normalized[http://identifiers.org/BTO:0000131-https://identifiers.org/BTO:0000131] FAILED tests/metadata/test_annotator.py::test_annotation_resource_of_a_known_collection_is_normalized[UO:0000021-https://identifiers.org/UO:0000021] FAILED tests/metadata/test_annotator.py::test_annotation_resource_of_a_known_collection_is_normalized[http://identifiers.org/sbmlutils.test.collection1/1406-https://identifiers.org/sbmlutils.test.collection1/1406] FAILED tests/metadata/test_annotator.py::test_annotation_resource_of_a_known_collection_is_normalized[http://identifiers.org/sbmlutils.test.collection1/XX:0000040-https://identifiers.org/sbmlutils.test.collection1/XX:0000040] FAILED tests/metadata/test_annotator.py::test_annotation_resource_of_a_known_collection_is_normalized[https://identifiers.org/SBMLUTILS.TEST.COLLECTION1:0000012-https://identifiers.org/SBMLUTILS.TEST.COLLECTION1:0000012] FAILED tests/metadata/test_annotator.py::test_annotation_resource_of_a_known_collection_is_normalized[http://identifiers.org/chebi/000000035-https://identifiers.org/chebi/000000035] FAILED tests/metadata/test_annotator.py::test_annotation_resource_of_a_known_collection_is_normalized[urn:miriam:sbmlutils.test.collection1:bar-https://identifiers.org/sbmlutils.test.collection1/bar] FAILED tests/metadata/test_annotator.py::test_annotation_losses_are_reported_once_per_collection FAILED tests/metadata/test_annotator.py::test_annotation_losses_do_not_leak_between_documents FAILED tests/metadata/test_annotator.py::test_annotation_loss_without_a_collection_is_grouped_as_such FAILED tests/metadata/test_annotator.py::test_annotation_loss_outside_a_document_is_reported_per_resource FAILED tests/test_construction_diagnostics.py::test_retained_annotation_is_informational FAILED tests/test_distrib.py::test_sabiork_uncertainty - pymetadata.webservic... FAILED tests/test_factory.py::test_reaction_modifier_keeps_sbase_fields - pym... FAILED tests/test_factory.py::test_reaction_reactant_keeps_name_notes_and_annotations FAILED tests/test_factory.py::test_an_annotation_which_is_neither_an_annotation_nor_a_tuple_raises[second] FAILED tests/test_package_roundtrip.py::test_roundtrip_document_returns_both_documents FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_fbc_strict FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_gene_products FAILED tests/test_package_roundtrip.py::test_roundtrip_loses_only_the_sboterm_of_an_association_node[e_coli_core.xml] FAILED tests/test_package_roundtrip.py::test_roundtrip_loses_only_the_sboterm_of_an_association_node[e_coli_core_expression.xml] FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_objectives FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_bounds_charge_and_formula FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_the_whole_fbc_content[e_coli_core.xml.gz] FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_the_whole_fbc_content[Recon3D.xml.gz] FAILED tests/test_package_roundtrip.py::test_roundtrip_flattens_exactly_the_two_pinned_associations FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[urn:miriam:chebi:CHEBI%3A33699] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[urn:miriam:uniprot:P03023] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[urn:miriam:obo.go:GO%3A0005623] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[urn:miriam:biomodels.sbo:SBO%3A0000247] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[urn:miriam:kegg.compound:C00031] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[urn:miriam:taxonomy:9606] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[urn:miriam:pubmed:10643997] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[urn:miriam:ec-code:1.1.1.1] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[urn:miriam:reactome:REACT_1234] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[urn:miriam:sbmlutils.test.collection1:bar] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[urn:miriam:sbmlutils.test.collection1:BAR%3A123] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/chebi/CHEBI:12965] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/uniprot/P03023] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/go/GO:0005623] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/obo.go/GO:0005623] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/biomodels.sbo/SBO:0000247] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/kegg.compound/C00031] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/pubmed/10643997] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/bigg.metabolite/glc__D] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/asap/ABE-0000027] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[https://identifiers.org/taxonomy/9606] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/ec-code/1.1.1.1] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/yaaK] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/sbmlutils.test.collection1/1406] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/sbmlutils.test.collection1/XX:0000040] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/chebi/000000035] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/BTO:0000131] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/SBO:0000625] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/FMA:12274] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/CHEBI:33699] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/GO:0005623] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/uniprot:P03023] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/kegg.compound:C00031] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[UO:0000021] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[CHEBI:33699] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[GO:0005623] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[SBO:0000247] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[uniprot:P03023] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/iex?] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/iex?a=b] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/iex#fragment] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/iex/] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/refseq_synonym/iex?#] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/chebi/CHEBI:12965/?a=b#c] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[https://identifiers.org/uniprot/P03023?] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/BTO:0000131?] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/BTO:0000131/] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/uniprot:P03023?a=b#c] FAILED tests/test_package_roundtrip.py::test_identifiers_org_is_what_pymetadata_does[http://identifiers.org/sbmlutils.test.collection1/1406?] FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_the_whole_distrib_content[uncertainty.xml] FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_the_whole_distrib_content[e_coli_core_expression.xml] FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_the_whole_distrib_content[model.xml] FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_the_submodels_of_icg_body FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_the_ports_of_icg_body FAILED tests/test_package_roundtrip.py::test_roundtrip_writes_each_port_exactly_once FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_external_model_definitions FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_the_comp_content_of_icg_body FAILED tests/test_package_roundtrip.py::test_roundtrip_of_a_flat_model_gains_no_comp_content FAILED tests/test_package_roundtrip.py::test_roundtrip_of_an_l3v1_comp_model_validates_at_its_own_version FAILED tests/test_package_roundtrip.py::test_key_value_pair_writes_every_field_it_can_carry FAILED tests/test_package_roundtrip.py::test_roundtrip_preserves_the_metadata_of_a_key_value_pair FAILED tests/test_package_semantics.py::test_comp_semantics_of_icg_body - pym... FAILED tests/test_package_semantics.py::test_comp_semantic_diff_sees_a_damaged_round_trip[drop the submodel] FAILED tests/test_package_semantics.py::test_comp_semantic_diff_sees_a_damaged_round_trip[drop the replaced element of the liver plasma volume] FAILED tests/test_package_semantics.py::test_comp_semantic_diff_sees_a_damaged_round_trip[drop the replaced element of the liver plasma concentration] ERROR tests/test_distrib.py::test_uncert_child_writes_meta_id_and_sbo_term[up_mean] ERROR tests/test_distrib.py::test_uncert_child_writes_meta_id_and_sbo_term[up_range] ERROR tests/test_distrib.py::test_uncert_child_writes_id_and_name[up_mean] - ... ERROR tests/test_distrib.py::test_uncert_child_writes_id_and_name[up_range] ERROR tests/test_distrib.py::test_uncert_child_writes_notes[up_mean] - pymeta... ERROR tests/test_distrib.py::test_uncert_child_writes_notes[up_range] - pymet... ERROR tests/test_distrib.py::test_uncert_child_writes_annotations[up_mean] - ... ERROR tests/test_distrib.py::test_uncert_child_writes_annotations[up_range] ERROR tests/test_distrib.py::test_uncert_child_writes_key_value_pairs[up_mean] ERROR tests/test_distrib.py::test_uncert_child_writes_key_value_pairs[up_range] 119 failed, 1327 passed, 75 skipped, 3 deselected, 10 errors in 419.49s (0:06:59) RPM build errors: error: Bad exit status from /var/tmp/rpm-tmp.Hn4Piw (%check) Bad exit status from /var/tmp/rpm-tmp.Hn4Piw (%check) Finish: rpmbuild python-sbmlutils-0.17.0-1.fc46.src.rpm Finish: build phase for python-sbmlutils-0.17.0-1.fc46.src.rpm INFO: chroot_scan: 1 files copied to /var/lib/copr-rpmbuild/results/chroot_scan INFO: /var/lib/mock/fedora-rawhide-x86_64-1792824742.145479/root/var/log/dnf5.log INFO: chroot_scan: creating tarball /var/lib/copr-rpmbuild/results/chroot_scan.tar.gz /bin/tar: Removing leading `/' from member names ERROR: Exception(/var/lib/copr-rpmbuild/results/python-sbmlutils-0.17.0-1.fc46.src.rpm) Config(fedora-rawhide-x86_64) 7 minutes 17 seconds INFO: Results and/or logs in: /var/lib/copr-rpmbuild/results INFO: Cleaning up build root ('cleanup_on_failure=True') Start: clean chroot INFO: unmounting tmpfs. Finish: clean chroot ERROR: Command failed: # /usr/bin/systemd-nspawn -q -M 9344dec18a004402aa760e779acd57c5 -D /var/lib/mock/fedora-rawhide-x86_64-1792824742.145479/root -a -u mockbuild --capability=cap_ipc_lock --capability=cap_ipc_lock --bind=/dev/btrfs-control --bind=/dev/mapper/control --bind=/dev/fuse --bind=/dev/loop-control --bind=/dev/loop0 --bind=/dev/loop1 --bind=/dev/loop2 --bind=/dev/loop3 --bind=/dev/loop4 --bind=/dev/loop5 --bind=/dev/loop6 --bind=/dev/loop7 --bind=/dev/loop8 --bind=/dev/loop9 --bind=/dev/loop10 --bind=/dev/loop11 --resolv-conf=off --resolv-conf=off --console=pipe --setenv=TERM=vt100 --setenv=SHELL=/bin/bash --setenv=HOME=/builddir --setenv=HOSTNAME=mock --setenv=PATH=/usr/bin:/bin:/usr/sbin:/sbin '--setenv=PROMPT_COMMAND=printf "\033]0;\007"' '--setenv=PS1= \s-\v\$ ' --setenv=LANG=C.UTF-8 bash --login -c '/usr/bin/rpmbuild -ba --noprep --noclean --target x86_64 /builddir/build/originals/python-sbmlutils.spec' Copr build error: Build failed