Warning: Permanently added '44.211.249.162' (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-44-x86_64 --chroot fedora-44-x86_64 Version: 1.10 PID: 15457 Logging PID: 15459 Task: {'allow_user_ssh': False, 'appstream': False, 'background': False, 'build_id': 11200695, 'buildroot_pkgs': [], 'chroot': 'fedora-44-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-44-x86_64/', 'id': 'copr_base', 'name': 'Copr repository', 'priority': None, 'repo_gpgcheck': False}, {'baseurl': 'https://download.copr.fedorainfracloud.org/results/mhough/neurofedora/fedora-44-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-44-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-4wtu3m6c/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-4wtu3m6c/python-sbmlutils', '--depth', '500', '--no-single-branch', '--recursive'] cwd: . rc: 0 stdout: stderr: Cloning into '/var/lib/copr-rpmbuild/workspace/workdir-4wtu3m6c/python-sbmlutils'... Running: git checkout b8a12e4556de21de570cf253073fba29bf0b3a85 -- cmd: ['git', 'checkout', 'b8a12e4556de21de570cf253073fba29bf0b3a85', '--'] cwd: /var/lib/copr-rpmbuild/workspace/workdir-4wtu3m6c/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-4wtu3m6c/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 154.4M 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-4wtu3m6c/python-sbmlutils/python-sbmlutils.spec --sources /var/lib/copr-rpmbuild/workspace/workdir-4wtu3m6c/python-sbmlutils --resultdir /var/lib/copr-rpmbuild/results --uniqueext 1792824740.810656 -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-4wtu3m6c/python-sbmlutils/python-sbmlutils.spec --sources /var/lib/copr-rpmbuild/workspace/workdir-4wtu3m6c/python-sbmlutils --resultdir /var/lib/copr-rpmbuild/results --uniqueext 1792824740.810656 -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-4wtu3m6c/python-sbmlutils/python-sbmlutils.spec) Config(fedora-44-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-44-x86_64-bootstrap-1792824740.810656/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:44 INFO: Pulling image: registry.fedoraproject.org/fedora:44 INFO: Tagging container image as mock-bootstrap-8ddb0ab3-cc4e-48c9-ae9d-e22032a6b989 INFO: Checking that 903b70f9e619fa34dd8f3037437f744fe864798688845371d98d2854af9730cb image matches host's architecture INFO: Copy content of container 903b70f9e619fa34dd8f3037437f744fe864798688845371d98d2854af9730cb to /var/lib/mock/fedora-44-x86_64-bootstrap-1792824740.810656/root INFO: mounting 903b70f9e619fa34dd8f3037437f744fe864798688845371d98d2854af9730cb with podman image mount INFO: image 903b70f9e619fa34dd8f3037437f744fe864798688845371d98d2854af9730cb as /var/lib/containers/storage/overlay/81a08d1449bb27f1f2a4b3a84015a3286388ad3a355ad4774b973bef6b54f865/merged INFO: umounting image 903b70f9e619fa34dd8f3037437f744fe864798688845371d98d2854af9730cb (/var/lib/containers/storage/overlay/81a08d1449bb27f1f2a4b3a84015a3286388ad3a355ad4774b973bef6b54f865/merged) with podman image umount INFO: Removing image mock-bootstrap-8ddb0ab3-cc4e-48c9-ae9d-e22032a6b989 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-44-x86_64-1792824740.810656/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.0.2-1.fc44.x86_64 rpm-sequoia-1.10.3-1.fc44.x86_64 dnf5-5.4.6.0-1.fc44.x86_64 dnf5-plugins-5.4.6.0-1.fc44.x86_64 Start: installing minimal buildroot with dnf5 Updating and loading repositories: updates 100% | 57.3 KiB/s | 23.1 KiB | 00m00s fedora 100% | 59.0 KiB/s | 23.8 KiB | 00m00s Additional repo copr_mhough_neurofedor 100% | 5.3 KiB/s | 1.5 KiB | 00m00s Copr repository 100% | 5.2 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package Arch Version Repository Size Installing group/module packages: bash x86_64 0:5.3.9-3.fc44 fedora 8.5 MiB bzip2 x86_64 0:1.0.8-23.fc44 fedora 95.0 KiB coreutils x86_64 0:9.10-5.fc44 updates 5.7 MiB cpio x86_64 0:2.15-9.fc44 fedora 1.1 MiB diffutils x86_64 0:3.12-5.fc44 fedora 1.6 MiB fedora-release-common noarch 0:44-18 updates 20.6 KiB findutils x86_64 1:4.10.0-7.fc44 fedora 1.9 MiB gawk x86_64 0:5.3.2-3.fc44 fedora 1.8 MiB glibc-minimal-langpack x86_64 0:2.43-9.fc44 updates 0.0 B grep x86_64 0:3.12-3.fc44 fedora 1.0 MiB gzip x86_64 0:1.14-2.fc44 fedora 401.6 KiB info x86_64 0:7.2-9.fc44 fedora 365.6 KiB patch x86_64 0:2.8-4.fc44 fedora 226.6 KiB redhat-rpm-config noarch 0:344-2.fc44 updates 183.7 KiB rpm-build x86_64 0:6.0.2-1.fc44 updates 294.6 KiB sed x86_64 0:4.9-7.fc44 fedora 857.2 KiB shadow-utils x86_64 2:4.19.0-7.fc44 updates 4.0 MiB tar x86_64 2:1.35-9.fc44 updates 3.0 MiB unzip x86_64 0:6.0-69.fc44 fedora 445.8 KiB util-linux x86_64 0:2.41.5-1.fc44 updates 3.5 MiB which x86_64 0:2.25-1.fc44 updates 83.6 KiB xz x86_64 1:5.8.2-2.fc44 fedora 1.3 MiB Installing dependencies: R-srpm-macros noarch 0:1.3.7-2.fc44 updates 3.5 KiB add-determinism x86_64 0:0.7.3-2.fc44 updates 2.2 MiB alternatives x86_64 0:1.33-5.fc44 fedora 62.1 KiB ansible-srpm-macros noarch 0:1-20.1.fc44 fedora 35.7 KiB audit-libs x86_64 0:4.2.1-1.fc44 updates 390.5 KiB binutils x86_64 0:2.46.1-1.fc44 updates 28.2 MiB build-reproducibility-srpm-macros noarch 0:0.7.3-2.fc44 updates 1.2 KiB bzip2-libs x86_64 0:1.0.8-23.fc44 fedora 80.5 KiB ca-certificates noarch 0:2026.2.92_v9.0.319-2.fc44 updates 2.7 MiB cmake-srpm-macros noarch 0:4.3.0-1.fc44 fedora 524.0 B coreutils-common x86_64 0:9.10-5.fc44 updates 10.7 MiB crypto-policies noarch 0:20251128-3.git19878fe.fc44 fedora 132.6 KiB curl x86_64 0:8.18.0-14.fc44 updates 480.0 KiB cyrus-sasl-lib x86_64 0:2.1.28-35.fc44 fedora 2.3 MiB debugedit x86_64 0:5.3-2.fc44 updates 220.8 KiB dwz x86_64 0:0.16-3.fc44 fedora 290.9 KiB ed x86_64 0:1.22.5-2.fc44 fedora 149.7 KiB efi-srpm-macros noarch 0:6-6.fc44 fedora 40.2 KiB elfutils x86_64 0:0.196-1.fc44 updates 3.2 MiB elfutils-debuginfod-client x86_64 0:0.196-1.fc44 updates 83.8 KiB elfutils-default-yama-scope noarch 0:0.196-1.fc44 updates 1.8 KiB elfutils-libelf x86_64 0:0.196-1.fc44 updates 1.4 MiB elfutils-libs x86_64 0:0.196-1.fc44 updates 715.4 KiB erlang-srpm-macros noarch 0:0.4.0-1.fc44 updates 2.0 KiB fedora-gpg-keys noarch 0:44-2 updates 257.6 KiB fedora-release noarch 0:44-18 updates 0.0 B fedora-release-identity-basic noarch 0:44-18 updates 629.0 B fedora-repos noarch 0:44-2 updates 4.9 KiB file x86_64 0:5.46-10.fc44 updates 100.1 KiB file-libs x86_64 0:5.46-10.fc44 updates 11.9 MiB filesystem x86_64 0:3.18-52.fc44 fedora 112.0 B filesystem-srpm-macros noarch 0:3.18-52.fc44 fedora 38.2 KiB fonts-srpm-macros noarch 1:5.0.0-2.fc44 fedora 55.8 KiB forge-srpm-macros noarch 0:0.4.0-4.fc44 fedora 38.9 KiB fpc-srpm-macros noarch 0:1.3-16.fc44 fedora 144.0 B gap-srpm-macros noarch 0:2-2.fc44 fedora 2.1 KiB gdb-minimal x86_64 0:17.2-4.fc44 updates 14.2 MiB gdbm-libs x86_64 1:1.23-11.fc44 fedora 129.6 KiB ghc-srpm-macros noarch 0:1.10-1.fc44 fedora 792.0 B glibc x86_64 0:2.43-9.fc44 updates 6.9 MiB glibc-common x86_64 0:2.43-9.fc44 updates 1.0 MiB glibc-gconv-extra x86_64 0:2.43-9.fc44 updates 7.4 MiB gmp x86_64 1:6.3.0-5.fc44 fedora 815.2 KiB gnat-srpm-macros noarch 0:7-2.fc44 fedora 1.0 KiB gnome-srpm-macros noarch 0:1.0-1.fc44 updates 3.5 KiB gnulib-l10n noarch 0:20241231-2.fc44 fedora 655.0 KiB gnupg2 x86_64 0:2.4.9-16.fc44 updates 6.5 MiB gnupg2-dirmngr x86_64 0:2.4.9-16.fc44 updates 634.0 KiB gnupg2-gpg-agent x86_64 0:2.4.9-16.fc44 updates 686.6 KiB gnupg2-gpgconf x86_64 0:2.4.9-16.fc44 updates 249.7 KiB gnupg2-keyboxd x86_64 0:2.4.9-16.fc44 updates 201.2 KiB gnupg2-verify x86_64 0:2.4.9-16.fc44 updates 360.3 KiB gnutls x86_64 0:3.8.13-1.fc44 updates 3.8 MiB go-srpm-macros noarch 0:3.8.0-2.fc44 fedora 61.9 KiB gpgverify noarch 0:2.2-4.fc44 fedora 8.7 KiB ima-evm-utils-libs x86_64 0:1.6.2-8.fc44 fedora 60.6 KiB jansson x86_64 0:2.14-4.fc44 fedora 88.9 KiB java-srpm-macros noarch 0:1-8.fc44 fedora 870.0 B json-c x86_64 0:0.18-8.fc44 fedora 82.6 KiB kernel-srpm-macros noarch 0:1.0-28.fc44 fedora 1.9 KiB keyutils-libs x86_64 0:1.6.3-7.fc44 fedora 54.2 KiB krb5-libs x86_64 0:1.22.2-4.fc44 updates 2.4 MiB libacl x86_64 0:2.4.0-1.fc44 updates 39.9 KiB libarchive x86_64 0:3.8.7-1.fc44 updates 1.0 MiB libassuan x86_64 0:2.5.7-5.fc44 fedora 163.8 KiB libattr x86_64 0:2.6.0-1.fc44 updates 24.3 KiB libblkid x86_64 0:2.41.5-1.fc44 updates 274.3 KiB libbrotli x86_64 0:1.2.0-3.fc44 fedora 865.0 KiB libcap x86_64 0:2.78-1.fc44 updates 212.1 KiB libcap-ng x86_64 0:0.9.6-1.fc44 updates 68.8 KiB libcbor x86_64 0:0.13.0-2.fc44 fedora 79.5 KiB libcom_err x86_64 0:1.47.3-4.fc44 fedora 63.0 KiB libcurl x86_64 0:8.18.0-14.fc44 updates 1.0 MiB libeconf x86_64 0:0.7.9-3.fc44 fedora 64.8 KiB libevent x86_64 0:2.1.13-1.fc44 updates 980.7 KiB libfdisk x86_64 0:2.41.5-1.fc44 updates 388.3 KiB libffi x86_64 0:3.5.2-2.fc44 fedora 87.7 KiB libfido2 x86_64 0:1.16.0-5.fc44 fedora 246.4 KiB libfsverity x86_64 0:1.6-4.fc44 fedora 28.4 KiB libgcc x86_64 0:16.2.1-2.fc44 updates 270.6 KiB libgcrypt x86_64 0:1.12.2-1.fc44 updates 1.7 MiB libgomp x86_64 0:16.2.1-2.fc44 updates 577.5 KiB libgpg-error x86_64 0:1.58-2.fc44 fedora 941.6 KiB libidn2 x86_64 0:2.3.8-3.fc44 fedora 556.4 KiB libksba x86_64 0:1.6.7-5.fc44 fedora 414.4 KiB liblastlog2 x86_64 0:2.41.5-1.fc44 updates 41.6 KiB libmount x86_64 0:2.41.5-1.fc44 updates 392.6 KiB libnghttp2 x86_64 0:1.68.0-5.fc44 updates 166.1 KiB libnghttp3 x86_64 0:1.18.0-1.fc44 updates 163.4 KiB libpfm x86_64 0:4.13.0-20.fc44 updates 1.7 MiB libpkgconf x86_64 0:2.5.1-1.fc44 fedora 90.1 KiB libpsl x86_64 0:0.21.5-7.fc44 fedora 76.3 KiB libselinux x86_64 0:3.11-2.fc44 updates 205.2 KiB libselinux-utils x86_64 0:3.11-2.fc44 updates 305.8 KiB libsemanage x86_64 0:3.11-1.fc44 updates 316.4 KiB libsepol x86_64 0:3.11-1.fc44 updates 862.1 KiB libsmartcols x86_64 0:2.41.5-1.fc44 updates 188.3 KiB libssh x86_64 0:0.12.2-1.fc44 updates 725.5 KiB libssh-config noarch 0:0.12.2-1.fc44 updates 277.0 B libstdc++ x86_64 0:16.2.1-2.fc44 updates 3.1 MiB libtasn1 x86_64 0:4.21.0-1.fc44 fedora 180.6 KiB libtool-ltdl x86_64 0:2.5.4-10.fc44 fedora 70.0 KiB libunistring x86_64 0:1.1-11.fc44 fedora 1.7 MiB libusb1 x86_64 0:1.0.30-1.fc44 updates 176.0 KiB libuuid x86_64 0:2.41.5-1.fc44 updates 37.2 KiB libverto x86_64 0:0.3.2-12.fc44 fedora 25.3 KiB libxcrypt x86_64 0:4.5.2-3.fc44 fedora 293.2 KiB libxml2 x86_64 0:2.12.10-6.fc44 fedora 1.8 MiB libzstd x86_64 0:1.5.7-5.fc44 fedora 956.1 KiB linkdupes x86_64 0:0.7.3-2.fc44 updates 780.9 KiB lua-libs x86_64 0:5.4.8-5.fc44 fedora 281.7 KiB lua-srpm-macros noarch 0:1-17.fc44 fedora 1.3 KiB lz4-libs x86_64 0:1.10.0-4.fc44 fedora 157.3 KiB mpfr x86_64 0:4.2.2-3.fc44 fedora 849.1 KiB ncurses-base noarch 0:6.6-1.fc44 fedora 329.7 KiB ncurses-libs x86_64 0:6.6-1.fc44 fedora 968.9 KiB nettle x86_64 0:3.10.1-3.fc44 fedora 794.3 KiB ngtcp2 x86_64 0:1.22.1-1.fc44 updates 338.2 KiB ngtcp2-crypto-ossl x86_64 0:1.22.1-1.fc44 updates 51.6 KiB npth x86_64 0:1.8-4.fc44 fedora 49.5 KiB ocaml-srpm-macros noarch 0:11-3.fc44 fedora 1.9 KiB openblas-srpm-macros noarch 0:2-21.fc44 fedora 112.0 B openldap x86_64 0:2.6.15-1.fc44 updates 671.3 KiB openssl-libs x86_64 1:3.5.9-1.fc44 updates 9.2 MiB p11-kit x86_64 0:0.26.5-1.fc44 updates 2.6 MiB p11-kit-trust x86_64 0:0.26.5-1.fc44 updates 478.3 KiB package-notes-srpm-macros noarch 0:0.20-1.fc44 updates 1.6 KiB pam-libs x86_64 0:1.7.2-2.fc44 updates 130.5 KiB pcre2 x86_64 0:10.47-1.fc44.1 fedora 718.6 KiB pcre2-syntax noarch 0:10.47-1.fc44.1 fedora 281.9 KiB perl-srpm-macros noarch 0:1-61.fc44 fedora 861.0 B pkgconf x86_64 0:2.5.1-1.fc44 fedora 92.7 KiB pkgconf-m4 noarch 0:2.5.1-1.fc44 fedora 14.3 KiB pkgconf-pkg-config x86_64 0:2.5.1-1.fc44 fedora 989.0 B policycoreutils x86_64 0:3.11-2.fc44 updates 884.8 KiB popt x86_64 0:1.19-10.fc44 fedora 132.6 KiB publicsuffix-list-dafsa noarch 0:20260116-1.fc44 fedora 70.4 KiB pyproject-srpm-macros noarch 0:1.24.0-1.fc44 updates 3.4 KiB python-srpm-macros noarch 0:3.14-12.fc44 fedora 51.6 KiB qt5-srpm-macros noarch 0:5.15.18-2.fc44 fedora 500.0 B qt6-srpm-macros noarch 0:6.11.2-1.fc44 updates 472.0 B readline x86_64 0:8.3-4.fc44 fedora 519.5 KiB rpm x86_64 0:6.0.2-1.fc44 updates 3.1 MiB rpm-build-libs x86_64 0:6.0.2-1.fc44 updates 276.3 KiB rpm-libs x86_64 0:6.0.2-1.fc44 updates 961.2 KiB rpm-plugin-selinux x86_64 0:6.0.2-1.fc44 updates 11.9 KiB rpm-sequoia x86_64 0:1.10.3-1.fc44 updates 2.4 MiB rpm-sign-libs x86_64 0:6.0.2-1.fc44 updates 39.6 KiB rust-srpm-macros noarch 0:28.5-1.fc44 updates 5.5 KiB selinux-policy noarch 0:44.11-1.fc44 updates 32.1 KiB selinux-policy-targeted noarch 0:44.11-1.fc44 updates 18.6 MiB setup noarch 0:2.15.0-28.fc44 fedora 724.9 KiB sqlite-libs x86_64 0:3.51.2-2.fc44 updates 1.6 MiB systemd-libs x86_64 0:259.10-1.fc44 updates 2.5 MiB systemd-standalone-sysusers x86_64 0:259.10-1.fc44 updates 305.7 KiB tpm2-tss x86_64 0:4.1.3-9.fc44 fedora 1.6 MiB tree-sitter-srpm-macros noarch 0:0.4.2-2.fc44 fedora 8.3 KiB util-linux-core x86_64 0:2.41.5-1.fc44 updates 1.5 MiB xxhash-libs x86_64 0:0.8.4-1.fc44 updates 94.0 KiB xz-libs x86_64 1:5.8.2-2.fc44 fedora 217.7 KiB zig-srpm-macros noarch 0:1-8.fc44 fedora 1.3 KiB zip x86_64 0:3.0-45.fc44 fedora 698.0 KiB zlib-ng-compat x86_64 0:2.3.3-3.fc44 fedora 165.6 KiB zstd x86_64 0:1.5.7-5.fc44 fedora 502.4 KiB Installing groups: Buildsystem building group Transaction Summary: Installing: 186 packages Total size of inbound packages is 69 MiB. Need to download 0 B. After this operation, 227 MiB extra will be used (install 227 MiB, remove 0 B). [ 1/186] bzip2-0:1.0.8-23.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 2/186] unzip-0:6.0-69.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 3/186] cpio-0:2.15-9.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 4/186] bash-0:5.3.9-3.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 5/186] grep-0:3.12-3.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 6/186] patch-0:2.8-4.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 7/186] sed-0:4.9-7.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 8/186] diffutils-0:3.12-5.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 9/186] findutils-1:4.10.0-7.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 10/186] gzip-0:1.14-2.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 11/186] info-0:7.2-9.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 12/186] xz-1:5.8.2-2.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 13/186] tar-2:1.35-9.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 14/186] redhat-rpm-config-0:344-2.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 15/186] rpm-build-0:6.0.2-1.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 16/186] which-0:2.25-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 17/186] coreutils-0:9.10-5.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 18/186] shadow-utils-2:4.19.0-7.fc44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 19/186] util-linux-0:2.41.5-1.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 20/186] fedora-release-common-0:44-18 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 21/186] gawk-0:5.3.2-3.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 22/186] glibc-minimal-langpack-0:2.43 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 23/186] bzip2-libs-0:1.0.8-23.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 24/186] filesystem-0:3.18-52.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 25/186] ncurses-libs-0:6.6-1.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 26/186] pcre2-0:10.47-1.fc44.1.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 27/186] ed-0:1.22.5-2.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 28/186] xz-libs-1:5.8.2-2.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 29/186] gnome-srpm-macros-0:1.0-1.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 30/186] ansible-srpm-macros-0:1-20.1. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 31/186] cmake-srpm-macros-0:4.3.0-1.f 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 32/186] dwz-0:0.16-3.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 33/186] efi-srpm-macros-0:6-6.fc44.no 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 34/186] filesystem-srpm-macros-0:3.18 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 35/186] fonts-srpm-macros-1:5.0.0-2.f 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 36/186] forge-srpm-macros-0:0.4.0-4.f 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 37/186] fpc-srpm-macros-0:1.3-16.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 38/186] gap-srpm-macros-0:2-2.fc44.no 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 39/186] ghc-srpm-macros-0:1.10-1.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 40/186] gnat-srpm-macros-0:7-2.fc44.n 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 41/186] go-srpm-macros-0:3.8.0-2.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 42/186] java-srpm-macros-0:1-8.fc44.n 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 43/186] kernel-srpm-macros-0:1.0-28.f 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 44/186] lua-srpm-macros-0:1-17.fc44.n 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 45/186] ocaml-srpm-macros-0:11-3.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 46/186] openblas-srpm-macros-0:2-21.f 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 47/186] perl-srpm-macros-0:1-61.fc44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 48/186] python-srpm-macros-0:3.14-12. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 49/186] qt5-srpm-macros-0:5.15.18-2.f 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 50/186] tree-sitter-srpm-macros-0:0.4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 51/186] zig-srpm-macros-0:1-8.fc44.no 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 52/186] zip-0:3.0-45.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 53/186] rpm-0:6.0.2-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 54/186] popt-0:1.19-10.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 55/186] readline-0:8.3-4.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 56/186] zstd-0:1.5.7-5.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 57/186] coreutils-common-0:9.10-5.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 58/186] gmp-1:6.3.0-5.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 59/186] libeconf-0:0.7.9-3.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 60/186] libxcrypt-0:4.5.2-3.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 61/186] setup-0:2.15.0-28.fc44.noarch 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 62/186] util-linux-core-0:2.41.5-1.fc 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 63/186] zlib-ng-compat-0:2.3.3-3.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 64/186] mpfr-0:4.2.2-3.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 65/186] glibc-common-0:2.43-9.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 66/186] ncurses-base-0:6.6-1.fc44.noa 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 67/186] pcre2-syntax-0:10.47-1.fc44.1 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 68/186] libzstd-0:1.5.7-5.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 69/186] gnulib-l10n-0:20241231-2.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 70/186] rpm-libs-0:6.0.2-1.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 71/186] glibc-0:2.43-9.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 72/186] lua-libs-0:5.4.8-5.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 73/186] rpm-build-libs-0:6.0.2-1.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 74/186] glibc-gconv-extra-0:2.43-9.fc 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 75/186] rpm-sign-libs-0:6.0.2-1.fc44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 76/186] ima-evm-utils-libs-0:1.6.2-8. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 77/186] libfsverity-0:1.6-4.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 78/186] tpm2-tss-0:4.1.3-9.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 79/186] json-c-0:0.18-8.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 80/186] libgcc-0:16.2.1-2.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 81/186] libstdc++-0:16.2.1-2.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 82/186] libusb1-0:1.0.30-1.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 83/186] libuuid-0:2.41.5-1.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 84/186] libmount-0:2.41.5-1.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 85/186] libblkid-0:2.41.5-1.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 86/186] openssl-libs-1:3.5.9-1.fc44.x 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 87/186] crypto-policies-0:20251128-3. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 88/186] libacl-0:2.4.0-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 89/186] libselinux-0:3.11-2.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 90/186] libsepol-0:3.11-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 91/186] libattr-0:2.6.0-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 92/186] elfutils-libelf-0:0.196-1.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 93/186] elfutils-libs-0:0.196-1.fc44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 94/186] elfutils-0:0.196-1.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 95/186] elfutils-debuginfod-client-0: 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 96/186] libsmartcols-0:2.41.5-1.fc44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 97/186] systemd-libs-0:259.10-1.fc44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 98/186] audit-libs-0:4.2.1-1.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 99/186] libcap-ng-0:0.9.6-1.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [100/186] libfdisk-0:2.41.5-1.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [101/186] liblastlog2-0:2.41.5-1.fc44.x 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [102/186] pam-libs-0:1.7.2-2.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [103/186] libsemanage-0:3.11-1.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [104/186] gnupg2-0:2.4.9-16.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [105/186] gpgverify-0:2.2-4.fc44.noarch 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [106/186] gnupg2-dirmngr-0:2.4.9-16.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [107/186] gnupg2-gpg-agent-0:2.4.9-16.f 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [108/186] gnupg2-gpgconf-0:2.4.9-16.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [109/186] gnupg2-keyboxd-0:2.4.9-16.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [110/186] gnupg2-verify-0:2.4.9-16.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [111/186] libassuan-0:2.5.7-5.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [112/186] libgpg-error-0:1.58-2.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [113/186] npth-0:1.8-4.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [114/186] libksba-0:1.6.7-5.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [115/186] libcap-0:2.78-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [116/186] rpm-sequoia-0:1.10.3-1.fc44.x 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [117/186] sqlite-libs-0:3.51.2-2.fc44.x 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [118/186] file-libs-0:5.46-10.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [119/186] file-0:5.46-10.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [120/186] libgomp-0:16.2.1-2.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [121/186] binutils-0:2.46.1-1.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [122/186] alternatives-0:1.33-5.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [123/186] jansson-0:2.14-4.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [124/186] debugedit-0:5.3-2.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [125/186] libarchive-0:3.8.7-1.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [126/186] libxml2-0:2.12.10-6.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [127/186] lz4-libs-0:1.10.0-4.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [128/186] pkgconf-pkg-config-0:2.5.1-1. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [129/186] pkgconf-0:2.5.1-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [130/186] pkgconf-m4-0:2.5.1-1.fc44.noa 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [131/186] libpkgconf-0:2.5.1-1.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [132/186] curl-0:8.18.0-14.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [133/186] R-srpm-macros-0:1.3.7-2.fc44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [134/186] build-reproducibility-srpm-ma 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [135/186] add-determinism-0:0.7.3-2.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [136/186] linkdupes-0:0.7.3-2.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [137/186] erlang-srpm-macros-0:0.4.0-1. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [138/186] package-notes-srpm-macros-0:0 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [139/186] pyproject-srpm-macros-0:1.24. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [140/186] qt6-srpm-macros-0:6.11.2-1.fc 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [141/186] rust-srpm-macros-0:28.5-1.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [142/186] ca-certificates-0:2026.2.92_v 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [143/186] libgcrypt-0:1.12.2-1.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [144/186] gnutls-0:3.8.13-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [145/186] libidn2-0:2.3.8-3.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [146/186] libtasn1-0:4.21.0-1.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [147/186] libunistring-0:1.1-11.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [148/186] nettle-0:3.10.1-3.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [149/186] openldap-0:2.6.15-1.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [150/186] cyrus-sasl-lib-0:2.1.28-35.fc 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [151/186] libtool-ltdl-0:2.5.4-10.fc44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [152/186] gdbm-libs-1:1.23-11.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [153/186] fedora-repos-0:44-2.noarch 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [154/186] fedora-gpg-keys-0:44-2.noarch 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [155/186] elfutils-default-yama-scope-0 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [156/186] libpfm-0:4.13.0-20.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [157/186] p11-kit-0:0.26.5-1.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [158/186] libffi-0:3.5.2-2.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [159/186] p11-kit-trust-0:0.26.5-1.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [160/186] libevent-0:2.1.13-1.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [161/186] fedora-release-0:44-18.noarch 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [162/186] systemd-standalone-sysusers-0 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [163/186] gdb-minimal-0:17.2-4.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [164/186] xxhash-libs-0:0.8.4-1.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [165/186] fedora-release-identity-basic 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [166/186] libcurl-0:8.18.0-14.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [167/186] libnghttp3-0:1.18.0-1.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [168/186] libssh-0:0.12.2-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [169/186] ngtcp2-0:1.22.1-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [170/186] libbrotli-0:1.2.0-3.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [171/186] libpsl-0:0.21.5-7.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [172/186] libssh-config-0:0.12.2-1.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [173/186] libfido2-0:1.16.0-5.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [174/186] publicsuffix-list-dafsa-0:202 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [175/186] libcbor-0:0.13.0-2.fc44.x86_6 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [176/186] ngtcp2-crypto-ossl-0:1.22.1-1 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [177/186] selinux-policy-targeted-0:44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [178/186] selinux-policy-0:44.11-1.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [179/186] rpm-plugin-selinux-0:6.0.2-1. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [180/186] policycoreutils-0:3.11-2.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [181/186] libselinux-utils-0:3.11-2.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [182/186] krb5-libs-0:1.22.2-4.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [183/186] keyutils-libs-0:1.6.3-7.fc44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [184/186] libcom_err-0:1.47.3-4.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [185/186] libverto-0:0.3.2-12.fc44.x86_ 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [186/186] libnghttp2-0:1.68.0-5.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded -------------------------------------------------------------------------------- [186/186] Total 100% | 0.0 B/s | 0.0 B | 00m00s Running transaction Importing OpenPGP key 0x6D9F90A6: UserID : "Fedora (44) " Fingerprint: 36F612DCF27F7D1A48A835E4DBFCF71C6D9F90A6 From : file:///usr/share/distribution-gpg-keys/fedora/RPM-GPG-KEY-fedora-44-primary The key was successfully imported. [ 1/188] Verify package files 100% | 707.0 B/s | 186.0 B | 00m00s [ 2/188] Prepare transaction 100% | 3.8 KiB/s | 186.0 B | 00m00s [ 3/188] Installing libgcc-0:16.2.1-2. 100% | 266.0 MiB/s | 272.3 KiB | 00m00s [ 4/188] Installing publicsuffix-list- 100% | 0.0 B/s | 71.1 KiB | 00m00s [ 5/188] Installing libssh-config-0:0. 100% | 0.0 B/s | 816.0 B | 00m00s [ 6/188] Installing fedora-release-ide 100% | 867.2 KiB/s | 888.0 B | 00m00s [ 7/188] Installing fedora-gpg-keys-0: 100% | 49.6 MiB/s | 355.3 KiB | 00m00s [ 8/188] Installing fedora-repos-0:44- 100% | 0.0 B/s | 5.7 KiB | 00m00s [ 9/188] Installing fedora-release-com 100% | 24.3 MiB/s | 24.9 KiB | 00m00s [ 10/188] Installing fedora-release-0:4 100% | 17.3 KiB/s | 124.0 B | 00m00s >>> Running sysusers scriptlet: setup-0:2.15.0-28.fc44.noarch >>> Finished sysusers scriptlet: setup-0:2.15.0-28.fc44.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. >>> [ 11/188] Installing setup-0:2.15.0-28. 100% | 51.0 MiB/s | 730.6 KiB | 00m00s >>> [RPM] /etc/hosts created as /etc/hosts.rpmnew [ 12/188] Installing filesystem-0:3.18- 100% | 3.1 MiB/s | 212.8 KiB | 00m00s [ 13/188] Installing rust-srpm-macros-0 100% | 0.0 B/s | 6.4 KiB | 00m00s [ 14/188] Installing qt6-srpm-macros-0: 100% | 0.0 B/s | 748.0 B | 00m00s [ 15/188] Installing package-notes-srpm 100% | 0.0 B/s | 2.1 KiB | 00m00s [ 16/188] Installing pkgconf-m4-0:2.5.1 100% | 0.0 B/s | 14.7 KiB | 00m00s [ 17/188] Installing gnulib-l10n-0:2024 100% | 215.5 MiB/s | 661.9 KiB | 00m00s [ 18/188] Installing coreutils-common-0 100% | 411.0 MiB/s | 10.7 MiB | 00m00s [ 19/188] Installing pcre2-syntax-0:10. 100% | 277.7 MiB/s | 284.3 KiB | 00m00s [ 20/188] Installing ncurses-base-0:6.6 100% | 86.7 MiB/s | 355.3 KiB | 00m00s [ 21/188] Installing bash-0:5.3.9-3.fc4 100% | 292.5 MiB/s | 8.5 MiB | 00m00s [ 22/188] Installing glibc-common-0:2.4 100% | 64.0 MiB/s | 1.0 MiB | 00m00s [ 23/188] Installing glibc-gconv-extra- 100% | 312.5 MiB/s | 7.5 MiB | 00m00s [ 24/188] Installing glibc-0:2.43-9.fc4 100% | 198.2 MiB/s | 6.9 MiB | 00m00s [ 25/188] Installing ncurses-libs-0:6.6 100% | 317.5 MiB/s | 975.4 KiB | 00m00s [ 26/188] Installing glibc-minimal-lang 100% | 0.0 B/s | 124.0 B | 00m00s [ 27/188] Installing zlib-ng-compat-0:2 100% | 162.6 MiB/s | 166.5 KiB | 00m00s [ 28/188] Installing bzip2-libs-0:1.0.8 100% | 0.0 B/s | 81.6 KiB | 00m00s [ 29/188] Installing libgpg-error-0:1.5 100% | 66.1 MiB/s | 947.5 KiB | 00m00s [ 30/188] Installing libstdc++-0:16.2.1 100% | 386.2 MiB/s | 3.1 MiB | 00m00s [ 31/188] Installing libassuan-0:2.5.7- 100% | 161.8 MiB/s | 165.7 KiB | 00m00s [ 32/188] Installing libgcrypt-0:1.12.2 100% | 414.7 MiB/s | 1.7 MiB | 00m00s [ 33/188] Installing readline-0:8.3-4.f 100% | 254.7 MiB/s | 521.6 KiB | 00m00s [ 34/188] Installing xz-libs-1:5.8.2-2. 100% | 213.7 MiB/s | 218.8 KiB | 00m00s [ 35/188] Installing gmp-1:6.3.0-5.fc44 100% | 399.2 MiB/s | 817.5 KiB | 00m00s [ 36/188] Installing libzstd-0:1.5.7-5. 100% | 311.6 MiB/s | 957.4 KiB | 00m00s [ 37/188] Installing elfutils-libelf-0: 100% | 481.0 MiB/s | 1.4 MiB | 00m00s [ 38/188] Installing libuuid-0:2.41.5-1 100% | 0.0 B/s | 38.3 KiB | 00m00s [ 39/188] Installing libacl-0:2.4.0-1.f 100% | 0.0 B/s | 40.7 KiB | 00m00s [ 40/188] Installing popt-0:1.19-10.fc4 100% | 68.0 MiB/s | 139.3 KiB | 00m00s [ 41/188] Installing systemd-libs-0:259 100% | 350.7 MiB/s | 2.5 MiB | 00m00s [ 42/188] Installing npth-0:1.8-4.fc44. 100% | 0.0 B/s | 50.6 KiB | 00m00s [ 43/188] Installing libblkid-0:2.41.5- 100% | 268.8 MiB/s | 275.3 KiB | 00m00s [ 44/188] Installing libxcrypt-0:4.5.2- 100% | 289.0 MiB/s | 295.9 KiB | 00m00s [ 45/188] Installing libsepol-0:3.11-1. 100% | 421.4 MiB/s | 863.0 KiB | 00m00s [ 46/188] Installing sqlite-libs-0:3.51 100% | 397.6 MiB/s | 1.6 MiB | 00m00s [ 47/188] Installing gnupg2-gpgconf-0:2 100% | 18.9 MiB/s | 251.8 KiB | 00m00s [ 48/188] Installing pcre2-0:10.47-1.fc 100% | 351.6 MiB/s | 720.0 KiB | 00m00s [ 49/188] Installing libselinux-0:3.11- 100% | 201.6 MiB/s | 206.5 KiB | 00m00s [ 50/188] Installing grep-0:3.12-3.fc44 100% | 66.8 MiB/s | 1.0 MiB | 00m00s [ 51/188] Installing sed-0:4.9-7.fc44.x 100% | 60.4 MiB/s | 865.4 KiB | 00m00s [ 52/188] Installing findutils-1:4.10.0 100% | 116.8 MiB/s | 1.9 MiB | 00m00s [ 53/188] Installing json-c-0:0.18-8.fc 100% | 81.9 MiB/s | 83.9 KiB | 00m00s [ 54/188] Installing libtasn1-0:4.21.0- 100% | 178.2 MiB/s | 182.4 KiB | 00m00s [ 55/188] Installing libunistring-0:1.1 100% | 346.9 MiB/s | 1.7 MiB | 00m00s [ 56/188] Installing libidn2-0:2.3.8-3. 100% | 61.0 MiB/s | 562.6 KiB | 00m00s [ 57/188] Installing crypto-policies-0: 100% | 38.5 MiB/s | 157.7 KiB | 00m00s [ 58/188] Installing xz-1:5.8.2-2.fc44. 100% | 76.1 MiB/s | 1.4 MiB | 00m00s [ 59/188] Installing libmount-0:2.41.5- 100% | 384.5 MiB/s | 393.7 KiB | 00m00s [ 60/188] Installing gnupg2-verify-0:2. 100% | 29.4 MiB/s | 361.7 KiB | 00m00s [ 61/188] Installing dwz-0:0.16-3.fc44. 100% | 23.8 MiB/s | 292.3 KiB | 00m00s [ 62/188] Installing mpfr-0:4.2.2-3.fc4 100% | 276.9 MiB/s | 850.8 KiB | 00m00s [ 63/188] Installing gawk-0:5.3.2-3.fc4 100% | 107.9 MiB/s | 1.8 MiB | 00m00s [ 64/188] Installing libksba-0:1.6.7-5. 100% | 203.6 MiB/s | 416.9 KiB | 00m00s [ 65/188] Installing unzip-0:6.0-69.fc4 100% | 33.8 MiB/s | 449.3 KiB | 00m00s [ 66/188] Installing file-libs-0:5.46-1 100% | 697.9 MiB/s | 11.9 MiB | 00m00s [ 67/188] Installing file-0:5.46-10.fc4 100% | 8.3 MiB/s | 101.6 KiB | 00m00s [ 68/188] Installing diffutils-0:3.12-5 100% | 98.3 MiB/s | 1.6 MiB | 00m00s [ 69/188] Installing libeconf-0:0.7.9-3 100% | 64.9 MiB/s | 66.4 KiB | 00m00s [ 70/188] Installing lua-libs-0:5.4.8-5 100% | 276.6 MiB/s | 283.2 KiB | 00m00s [ 71/188] Installing libattr-0:2.6.0-1. 100% | 0.0 B/s | 25.2 KiB | 00m00s [ 72/188] Installing libsmartcols-0:2.4 100% | 185.0 MiB/s | 189.5 KiB | 00m00s [ 73/188] Installing libcap-ng-0:0.9.6- 100% | 69.0 MiB/s | 70.6 KiB | 00m00s [ 74/188] Installing audit-libs-0:4.2.1 100% | 191.9 MiB/s | 393.1 KiB | 00m00s [ 75/188] Installing pam-libs-0:1.7.2-2 100% | 129.6 MiB/s | 132.7 KiB | 00m00s [ 76/188] Installing libcap-0:2.78-1.fc 100% | 16.3 MiB/s | 217.2 KiB | 00m00s [ 77/188] Installing libsemanage-0:3.11 100% | 310.7 MiB/s | 318.2 KiB | 00m00s [ 78/188] Installing alternatives-0:1.3 100% | 5.2 MiB/s | 63.6 KiB | 00m00s [ 79/188] Installing libffi-0:3.5.2-2.f 100% | 87.0 MiB/s | 89.1 KiB | 00m00s [ 80/188] Installing p11-kit-0:0.26.5-1 100% | 131.6 MiB/s | 2.6 MiB | 00m00s [ 81/188] Installing p11-kit-trust-0:0. 100% | 24.7 MiB/s | 480.1 KiB | 00m00s [ 82/188] Installing ngtcp2-0:1.22.1-1. 100% | 165.9 MiB/s | 339.8 KiB | 00m00s [ 83/188] Installing openssl-libs-1:3.5 100% | 383.9 MiB/s | 9.2 MiB | 00m00s [ 84/188] Installing coreutils-0:9.10-5 100% | 178.1 MiB/s | 5.7 MiB | 00m00s [ 85/188] Installing ca-certificates-0: 100% | 2.4 MiB/s | 2.5 MiB | 00m01s [ 86/188] Installing gzip-0:1.14-2.fc44 100% | 26.5 MiB/s | 407.1 KiB | 00m00s [ 87/188] Installing libfsverity-0:1.6- 100% | 0.0 B/s | 29.4 KiB | 00m00s [ 88/188] Installing rpm-sequoia-0:1.10 100% | 350.2 MiB/s | 2.5 MiB | 00m00s [ 89/188] Installing libevent-0:2.1.13- 100% | 320.5 MiB/s | 984.4 KiB | 00m00s [ 90/188] Installing ngtcp2-crypto-ossl 100% | 0.0 B/s | 52.5 KiB | 00m00s [ 91/188] Installing liblastlog2-0:2.41 100% | 7.1 MiB/s | 43.7 KiB | 00m00s [ 92/188] Installing util-linux-core-0: 100% | 82.2 MiB/s | 1.5 MiB | 00m00s [ 93/188] Installing zip-0:3.0-45.fc44. 100% | 49.0 MiB/s | 701.9 KiB | 00m00s [ 94/188] Installing gnupg2-keyboxd-0:2 100% | 39.5 MiB/s | 202.4 KiB | 00m00s [ 95/188] Installing libpsl-0:0.21.5-7. 100% | 75.6 MiB/s | 77.4 KiB | 00m00s [ 96/188] Installing tar-2:1.35-9.fc44. 100% | 148.9 MiB/s | 3.0 MiB | 00m00s [ 97/188] Installing linkdupes-0:0.7.3- 100% | 58.8 MiB/s | 782.3 KiB | 00m00s [ 98/188] Installing libselinux-utils-0 100% | 22.3 MiB/s | 320.2 KiB | 00m00s [ 99/188] Installing systemd-standalone 100% | 24.9 MiB/s | 306.2 KiB | 00m00s [100/188] Installing rpm-libs-0:6.0.2-1 100% | 313.4 MiB/s | 962.8 KiB | 00m00s [101/188] Installing libfdisk-0:2.41.5- 100% | 190.1 MiB/s | 389.4 KiB | 00m00s [102/188] Installing util-linux-0:2.41. 100% | 108.6 MiB/s | 3.6 MiB | 00m00s [103/188] Installing policycoreutils-0: 100% | 37.1 MiB/s | 913.0 KiB | 00m00s [104/188] Installing selinux-policy-0:4 100% | 1.9 MiB/s | 34.5 KiB | 00m00s [105/188] Installing selinux-policy-tar 100% | 216.0 MiB/s | 14.9 MiB | 00m00s [106/188] Installing libusb1-0:1.0.30-1 100% | 24.8 MiB/s | 177.7 KiB | 00m00s >>> Running sysusers scriptlet: tpm2-tss-0:4.1.3-9.fc44.x86_64 >>> Finished sysusers scriptlet: tpm2-tss-0:4.1.3-9.fc44.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/188] Installing tpm2-tss-0:4.1.3-9 100% | 272.2 MiB/s | 1.6 MiB | 00m00s [108/188] Installing ima-evm-utils-libs 100% | 60.4 MiB/s | 61.9 KiB | 00m00s [109/188] Installing gnupg2-gpg-agent-0 100% | 35.5 MiB/s | 690.5 KiB | 00m00s [110/188] Installing zstd-0:1.5.7-5.fc4 100% | 35.3 MiB/s | 506.0 KiB | 00m00s [111/188] Installing nettle-0:3.10.1-3. 100% | 259.6 MiB/s | 797.4 KiB | 00m00s [112/188] Installing gnutls-0:3.8.13-1. 100% | 384.9 MiB/s | 3.8 MiB | 00m00s [113/188] Installing libxml2-0:2.12.10- 100% | 110.7 MiB/s | 1.8 MiB | 00m00s [114/188] Installing bzip2-0:1.0.8-23.f 100% | 8.1 MiB/s | 99.5 KiB | 00m00s [115/188] Installing add-determinism-0: 100% | 128.4 MiB/s | 2.2 MiB | 00m00s [116/188] Installing build-reproducibil 100% | 0.0 B/s | 1.5 KiB | 00m00s [117/188] Installing cpio-0:2.15-9.fc44 100% | 73.6 MiB/s | 1.1 MiB | 00m00s [118/188] Installing ed-0:1.22.5-2.fc44 100% | 12.4 MiB/s | 152.0 KiB | 00m00s [119/188] Installing patch-0:2.8-4.fc44 100% | 18.6 MiB/s | 228.1 KiB | 00m00s [120/188] Installing libgomp-0:16.2.1-2 100% | 282.6 MiB/s | 578.9 KiB | 00m00s [121/188] Installing jansson-0:2.14-4.f 100% | 88.2 MiB/s | 90.3 KiB | 00m00s [122/188] Installing lz4-libs-0:1.10.0- 100% | 154.6 MiB/s | 158.4 KiB | 00m00s [123/188] Installing libarchive-0:3.8.7 100% | 326.0 MiB/s | 1.0 MiB | 00m00s [124/188] Installing libpkgconf-0:2.5.1 100% | 89.1 MiB/s | 91.3 KiB | 00m00s [125/188] Installing pkgconf-0:2.5.1-1. 100% | 7.7 MiB/s | 95.2 KiB | 00m00s [126/188] Installing pkgconf-pkg-config 100% | 161.2 KiB/s | 1.8 KiB | 00m00s [127/188] Installing libtool-ltdl-0:2.5 100% | 0.0 B/s | 71.1 KiB | 00m00s [128/188] Installing gdbm-libs-1:1.23-1 100% | 128.3 MiB/s | 131.3 KiB | 00m00s [129/188] Installing cyrus-sasl-lib-0:2 100% | 135.9 MiB/s | 2.3 MiB | 00m00s [130/188] Installing openldap-0:2.6.15- 100% | 219.8 MiB/s | 675.1 KiB | 00m00s [131/188] Installing gnupg2-dirmngr-0:2 100% | 32.7 MiB/s | 636.7 KiB | 00m00s [132/188] Installing gnupg2-0:2.4.9-16. 100% | 232.3 MiB/s | 6.5 MiB | 00m00s [133/188] Installing rpm-sign-libs-0:6. 100% | 0.0 B/s | 40.5 KiB | 00m00s [134/188] Installing gpgverify-0:2.2-4. 100% | 0.0 B/s | 9.4 KiB | 00m00s [135/188] Installing libpfm-0:4.13.0-20 100% | 576.1 MiB/s | 1.7 MiB | 00m00s [136/188] Installing xxhash-libs-0:0.8. 100% | 93.1 MiB/s | 95.4 KiB | 00m00s [137/188] Installing libnghttp3-0:1.18. 100% | 161.0 MiB/s | 164.8 KiB | 00m00s [138/188] Installing libbrotli-0:1.2.0- 100% | 282.3 MiB/s | 867.3 KiB | 00m00s [139/188] Installing libcbor-0:0.13.0-2 100% | 79.0 MiB/s | 80.9 KiB | 00m00s [140/188] Installing libfido2-0:1.16.0- 100% | 242.1 MiB/s | 247.9 KiB | 00m00s [141/188] Installing keyutils-libs-0:1. 100% | 0.0 B/s | 55.6 KiB | 00m00s [142/188] Installing libcom_err-0:1.47. 100% | 0.0 B/s | 64.1 KiB | 00m00s [143/188] Installing libverto-0:0.3.2-1 100% | 26.4 MiB/s | 27.1 KiB | 00m00s [144/188] Installing krb5-libs-0:1.22.2 100% | 342.1 MiB/s | 2.4 MiB | 00m00s [145/188] Installing libssh-0:0.12.2-1. 100% | 355.3 MiB/s | 727.6 KiB | 00m00s [146/188] Installing libnghttp2-0:1.68. 100% | 163.3 MiB/s | 167.3 KiB | 00m00s [147/188] Installing libcurl-0:8.18.0-1 100% | 332.7 MiB/s | 1.0 MiB | 00m00s [148/188] Installing curl-0:8.18.0-14.f 100% | 22.4 MiB/s | 482.7 KiB | 00m00s [149/188] Installing rpm-0:6.0.2-1.fc44 100% | 88.0 MiB/s | 2.6 MiB | 00m00s [150/188] Installing cmake-srpm-macros- 100% | 0.0 B/s | 804.0 B | 00m00s [151/188] Installing efi-srpm-macros-0: 100% | 0.0 B/s | 41.2 KiB | 00m00s [152/188] Installing java-srpm-macros-0 100% | 0.0 B/s | 1.1 KiB | 00m00s [153/188] Installing lua-srpm-macros-0: 100% | 0.0 B/s | 1.9 KiB | 00m00s [154/188] Installing tree-sitter-srpm-m 100% | 0.0 B/s | 9.3 KiB | 00m00s [155/188] Installing zig-srpm-macros-0: 100% | 0.0 B/s | 1.9 KiB | 00m00s [156/188] Installing filesystem-srpm-ma 100% | 0.0 B/s | 38.9 KiB | 00m00s [157/188] Installing elfutils-default-y 100% | 510.7 KiB/s | 2.0 KiB | 00m00s [158/188] Installing elfutils-libs-0:0. 100% | 233.5 MiB/s | 717.2 KiB | 00m00s [159/188] Installing elfutils-debuginfo 100% | 6.5 MiB/s | 86.2 KiB | 00m00s [160/188] Installing elfutils-0:0.196-1 100% | 158.2 MiB/s | 3.2 MiB | 00m00s [161/188] Installing binutils-0:2.46.1- 100% | 353.2 MiB/s | 28.3 MiB | 00m00s [162/188] Installing gdb-minimal-0:17.2 100% | 307.9 MiB/s | 14.2 MiB | 00m00s [163/188] Installing debugedit-0:5.3-2. 100% | 18.2 MiB/s | 224.0 KiB | 00m00s [164/188] Installing rpm-build-libs-0:6 100% | 270.7 MiB/s | 277.2 KiB | 00m00s [165/188] Installing qt5-srpm-macros-0: 100% | 0.0 B/s | 776.0 B | 00m00s [166/188] Installing perl-srpm-macros-0 100% | 0.0 B/s | 1.1 KiB | 00m00s [167/188] Installing openblas-srpm-macr 100% | 0.0 B/s | 392.0 B | 00m00s [168/188] Installing ocaml-srpm-macros- 100% | 0.0 B/s | 2.1 KiB | 00m00s [169/188] Installing kernel-srpm-macros 100% | 0.0 B/s | 2.3 KiB | 00m00s [170/188] Installing gnat-srpm-macros-0 100% | 0.0 B/s | 1.3 KiB | 00m00s [171/188] Installing ghc-srpm-macros-0: 100% | 0.0 B/s | 1.0 KiB | 00m00s [172/188] Installing gap-srpm-macros-0: 100% | 0.0 B/s | 2.7 KiB | 00m00s [173/188] Installing fpc-srpm-macros-0: 100% | 0.0 B/s | 420.0 B | 00m00s [174/188] Installing ansible-srpm-macro 100% | 0.0 B/s | 36.2 KiB | 00m00s [175/188] Installing gnome-srpm-macros- 100% | 1.0 MiB/s | 4.1 KiB | 00m00s [176/188] Installing rpm-build-0:6.0.2- 100% | 21.2 MiB/s | 303.5 KiB | 00m00s [177/188] Installing erlang-srpm-macros 100% | 0.0 B/s | 2.6 KiB | 00m00s [178/188] Installing pyproject-srpm-mac 100% | 0.0 B/s | 4.0 KiB | 00m00s [179/188] Installing redhat-rpm-config- 100% | 92.7 MiB/s | 189.9 KiB | 00m00s [180/188] Installing forge-srpm-macros- 100% | 0.0 B/s | 40.3 KiB | 00m00s [181/188] Installing fonts-srpm-macros- 100% | 0.0 B/s | 57.0 KiB | 00m00s [182/188] Installing go-srpm-macros-0:3 100% | 0.0 B/s | 63.0 KiB | 00m00s [183/188] Installing python-srpm-macros 100% | 0.0 B/s | 52.9 KiB | 00m00s [184/188] Installing R-srpm-macros-0:1. 100% | 0.0 B/s | 4.4 KiB | 00m00s [185/188] Installing rpm-plugin-selinux 100% | 0.0 B/s | 12.9 KiB | 00m00s [186/188] Installing which-0:2.25-1.fc4 100% | 6.4 MiB/s | 85.8 KiB | 00m00s [187/188] Installing shadow-utils-2:4.1 100% | 149.2 MiB/s | 4.0 MiB | 00m00s [188/188] Installing info-0:7.2-9.fc44. 100% | 57.5 KiB/s | 366.0 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-2.fc44.noarch add-determinism-0.7.3-2.fc44.x86_64 alternatives-1.33-5.fc44.x86_64 ansible-srpm-macros-1-20.1.fc44.noarch audit-libs-4.2.1-1.fc44.x86_64 bash-5.3.9-3.fc44.x86_64 binutils-2.46.1-1.fc44.x86_64 build-reproducibility-srpm-macros-0.7.3-2.fc44.noarch bzip2-1.0.8-23.fc44.x86_64 bzip2-libs-1.0.8-23.fc44.x86_64 ca-certificates-2026.2.92_v9.0.319-2.fc44.noarch cmake-srpm-macros-4.3.0-1.fc44.noarch coreutils-9.10-5.fc44.x86_64 coreutils-common-9.10-5.fc44.x86_64 cpio-2.15-9.fc44.x86_64 crypto-policies-20251128-3.git19878fe.fc44.noarch curl-8.18.0-14.fc44.x86_64 cyrus-sasl-lib-2.1.28-35.fc44.x86_64 debugedit-5.3-2.fc44.x86_64 diffutils-3.12-5.fc44.x86_64 dwz-0.16-3.fc44.x86_64 ed-1.22.5-2.fc44.x86_64 efi-srpm-macros-6-6.fc44.noarch elfutils-0.196-1.fc44.x86_64 elfutils-debuginfod-client-0.196-1.fc44.x86_64 elfutils-default-yama-scope-0.196-1.fc44.noarch elfutils-libelf-0.196-1.fc44.x86_64 elfutils-libs-0.196-1.fc44.x86_64 erlang-srpm-macros-0.4.0-1.fc44.noarch fedora-gpg-keys-44-2.noarch fedora-release-44-18.noarch fedora-release-common-44-18.noarch fedora-release-identity-basic-44-18.noarch fedora-repos-44-2.noarch file-5.46-10.fc44.x86_64 file-libs-5.46-10.fc44.x86_64 filesystem-3.18-52.fc44.x86_64 filesystem-srpm-macros-3.18-52.fc44.noarch findutils-4.10.0-7.fc44.x86_64 fonts-srpm-macros-5.0.0-2.fc44.noarch forge-srpm-macros-0.4.0-4.fc44.noarch fpc-srpm-macros-1.3-16.fc44.noarch gap-srpm-macros-2-2.fc44.noarch gawk-5.3.2-3.fc44.x86_64 gdb-minimal-17.2-4.fc44.x86_64 gdbm-libs-1.23-11.fc44.x86_64 ghc-srpm-macros-1.10-1.fc44.noarch glibc-2.43-9.fc44.x86_64 glibc-common-2.43-9.fc44.x86_64 glibc-gconv-extra-2.43-9.fc44.x86_64 glibc-minimal-langpack-2.43-9.fc44.x86_64 gmp-6.3.0-5.fc44.x86_64 gnat-srpm-macros-7-2.fc44.noarch gnome-srpm-macros-1.0-1.fc44.noarch gnulib-l10n-20241231-2.fc44.noarch gnupg2-2.4.9-16.fc44.x86_64 gnupg2-dirmngr-2.4.9-16.fc44.x86_64 gnupg2-gpg-agent-2.4.9-16.fc44.x86_64 gnupg2-gpgconf-2.4.9-16.fc44.x86_64 gnupg2-keyboxd-2.4.9-16.fc44.x86_64 gnupg2-verify-2.4.9-16.fc44.x86_64 gnutls-3.8.13-1.fc44.x86_64 go-srpm-macros-3.8.0-2.fc44.noarch gpg-pubkey-36f612dcf27f7d1a48a835e4dbfcf71c6d9f90a6-6786af3b gpgverify-2.2-4.fc44.noarch grep-3.12-3.fc44.x86_64 gzip-1.14-2.fc44.x86_64 ima-evm-utils-libs-1.6.2-8.fc44.x86_64 info-7.2-9.fc44.x86_64 jansson-2.14-4.fc44.x86_64 java-srpm-macros-1-8.fc44.noarch json-c-0.18-8.fc44.x86_64 kernel-srpm-macros-1.0-28.fc44.noarch keyutils-libs-1.6.3-7.fc44.x86_64 krb5-libs-1.22.2-4.fc44.x86_64 libacl-2.4.0-1.fc44.x86_64 libarchive-3.8.7-1.fc44.x86_64 libassuan-2.5.7-5.fc44.x86_64 libattr-2.6.0-1.fc44.x86_64 libblkid-2.41.5-1.fc44.x86_64 libbrotli-1.2.0-3.fc44.x86_64 libcap-2.78-1.fc44.x86_64 libcap-ng-0.9.6-1.fc44.x86_64 libcbor-0.13.0-2.fc44.x86_64 libcom_err-1.47.3-4.fc44.x86_64 libcurl-8.18.0-14.fc44.x86_64 libeconf-0.7.9-3.fc44.x86_64 libevent-2.1.13-1.fc44.x86_64 libfdisk-2.41.5-1.fc44.x86_64 libffi-3.5.2-2.fc44.x86_64 libfido2-1.16.0-5.fc44.x86_64 libfsverity-1.6-4.fc44.x86_64 libgcc-16.2.1-2.fc44.x86_64 libgcrypt-1.12.2-1.fc44.x86_64 libgomp-16.2.1-2.fc44.x86_64 libgpg-error-1.58-2.fc44.x86_64 libidn2-2.3.8-3.fc44.x86_64 libksba-1.6.7-5.fc44.x86_64 liblastlog2-2.41.5-1.fc44.x86_64 libmount-2.41.5-1.fc44.x86_64 libnghttp2-1.68.0-5.fc44.x86_64 libnghttp3-1.18.0-1.fc44.x86_64 libpfm-4.13.0-20.fc44.x86_64 libpkgconf-2.5.1-1.fc44.x86_64 libpsl-0.21.5-7.fc44.x86_64 libselinux-3.11-2.fc44.x86_64 libselinux-utils-3.11-2.fc44.x86_64 libsemanage-3.11-1.fc44.x86_64 libsepol-3.11-1.fc44.x86_64 libsmartcols-2.41.5-1.fc44.x86_64 libssh-0.12.2-1.fc44.x86_64 libssh-config-0.12.2-1.fc44.noarch libstdc++-16.2.1-2.fc44.x86_64 libtasn1-4.21.0-1.fc44.x86_64 libtool-ltdl-2.5.4-10.fc44.x86_64 libunistring-1.1-11.fc44.x86_64 libusb1-1.0.30-1.fc44.x86_64 libuuid-2.41.5-1.fc44.x86_64 libverto-0.3.2-12.fc44.x86_64 libxcrypt-4.5.2-3.fc44.x86_64 libxml2-2.12.10-6.fc44.x86_64 libzstd-1.5.7-5.fc44.x86_64 linkdupes-0.7.3-2.fc44.x86_64 lua-libs-5.4.8-5.fc44.x86_64 lua-srpm-macros-1-17.fc44.noarch lz4-libs-1.10.0-4.fc44.x86_64 mpfr-4.2.2-3.fc44.x86_64 ncurses-base-6.6-1.fc44.noarch ncurses-libs-6.6-1.fc44.x86_64 nettle-3.10.1-3.fc44.x86_64 ngtcp2-1.22.1-1.fc44.x86_64 ngtcp2-crypto-ossl-1.22.1-1.fc44.x86_64 npth-1.8-4.fc44.x86_64 ocaml-srpm-macros-11-3.fc44.noarch openblas-srpm-macros-2-21.fc44.noarch openldap-2.6.15-1.fc44.x86_64 openssl-libs-3.5.9-1.fc44.x86_64 p11-kit-0.26.5-1.fc44.x86_64 p11-kit-trust-0.26.5-1.fc44.x86_64 package-notes-srpm-macros-0.20-1.fc44.noarch pam-libs-1.7.2-2.fc44.x86_64 patch-2.8-4.fc44.x86_64 pcre2-10.47-1.fc44.1.x86_64 pcre2-syntax-10.47-1.fc44.1.noarch perl-srpm-macros-1-61.fc44.noarch pkgconf-2.5.1-1.fc44.x86_64 pkgconf-m4-2.5.1-1.fc44.noarch pkgconf-pkg-config-2.5.1-1.fc44.x86_64 policycoreutils-3.11-2.fc44.x86_64 popt-1.19-10.fc44.x86_64 publicsuffix-list-dafsa-20260116-1.fc44.noarch pyproject-srpm-macros-1.24.0-1.fc44.noarch python-srpm-macros-3.14-12.fc44.noarch qt5-srpm-macros-5.15.18-2.fc44.noarch qt6-srpm-macros-6.11.2-1.fc44.noarch readline-8.3-4.fc44.x86_64 redhat-rpm-config-344-2.fc44.noarch rpm-6.0.2-1.fc44.x86_64 rpm-build-6.0.2-1.fc44.x86_64 rpm-build-libs-6.0.2-1.fc44.x86_64 rpm-libs-6.0.2-1.fc44.x86_64 rpm-plugin-selinux-6.0.2-1.fc44.x86_64 rpm-sequoia-1.10.3-1.fc44.x86_64 rpm-sign-libs-6.0.2-1.fc44.x86_64 rust-srpm-macros-28.5-1.fc44.noarch sed-4.9-7.fc44.x86_64 selinux-policy-44.11-1.fc44.noarch selinux-policy-targeted-44.11-1.fc44.noarch setup-2.15.0-28.fc44.noarch shadow-utils-4.19.0-7.fc44.x86_64 sqlite-libs-3.51.2-2.fc44.x86_64 systemd-libs-259.10-1.fc44.x86_64 systemd-standalone-sysusers-259.10-1.fc44.x86_64 tar-1.35-9.fc44.x86_64 tpm2-tss-4.1.3-9.fc44.x86_64 tree-sitter-srpm-macros-0.4.2-2.fc44.noarch unzip-6.0-69.fc44.x86_64 util-linux-2.41.5-1.fc44.x86_64 util-linux-core-2.41.5-1.fc44.x86_64 which-2.25-1.fc44.x86_64 xxhash-libs-0.8.4-1.fc44.x86_64 xz-5.8.2-2.fc44.x86_64 xz-libs-5.8.2-2.fc44.x86_64 zig-srpm-macros-1-8.fc44.noarch zip-3.0-45.fc44.x86_64 zlib-ng-compat-2.3.3-3.fc44.x86_64 zstd-1.5.7-5.fc44.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.fc44.src.rpm Finish: rpmbuild -bs INFO: chroot_scan: 1 files copied to /var/lib/copr-rpmbuild/results/chroot_scan INFO: /var/lib/mock/fedora-44-x86_64-1792824740.810656/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-4wtu3m6c/python-sbmlutils/python-sbmlutils.spec) Config(child) 0 minutes 16 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.fc44.src.rpm) Config(fedora-44-x86_64) Start(bootstrap): chroot init INFO: mounting tmpfs at /var/lib/mock/fedora-44-x86_64-bootstrap-1792824740.810656/root. INFO: reusing tmpfs at /var/lib/mock/fedora-44-x86_64-bootstrap-1792824740.810656/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-44-x86_64-1792824740.810656/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.0.2-1.fc44.x86_64 rpm-sequoia-1.10.3-1.fc44.x86_64 dnf5-5.4.6.0-1.fc44.x86_64 dnf5-plugins-5.4.6.0-1.fc44.x86_64 Finish: chroot init Start: build phase for python-sbmlutils-0.17.0-1.fc44.src.rpm Start: build setup for python-sbmlutils-0.17.0-1.fc44.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.fc44.src.rpm Updating and loading repositories: updates 100% | 104.0 KiB/s | 23.1 KiB | 00m00s fedora 100% | 107.0 KiB/s | 23.8 KiB | 00m00s Additional repo copr_mhough_neurofedor 100% | 11.0 KiB/s | 1.5 KiB | 00m00s Copr repository 100% | 11.0 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package Arch Version Repository Size Installing: pyproject-rpm-macros noarch 0:1.24.0-1.fc44 updates 169.0 KiB python3-devel x86_64 0:3.14.8-1.fc44 updates 2.0 MiB python3-libsbml x86_64 0:5.20.5-100.fc44.biofedora copr_base 34.4 MiB python3-matplotlib x86_64 0:3.10.8-2.fc44 fedora 31.8 MiB python3-pytest noarch 0:8.4.2-2.fc44 fedora 22.5 MiB python3-roadrunner x86_64 0:2.10.0-11.fc44 copr_base 12.0 MiB Installing dependencies: abattis-cantarell-vf-fonts noarch 0:0.301-17.fc44 fedora 192.7 KiB blas x86_64 0:3.12.0-11.fc44 fedora 1.4 MiB cairo x86_64 0:1.18.6-1.fc44 updates 1.8 MiB default-fonts-core-sans noarch 0:4.3-1.fc44 fedora 11.9 KiB dejavu-sans-fonts noarch 0:2.37-29.fc44 fedora 5.5 MiB expat x86_64 0:2.8.5-1.fc44 updates 342.2 KiB flexiblas x86_64 0:3.5.0-2.fc44 fedora 38.0 KiB flexiblas-netlib x86_64 0:3.5.0-2.fc44 fedora 16.3 MiB flexiblas-openblas-openmp x86_64 0:3.5.0-2.fc44 fedora 39.1 KiB fontconfig x86_64 0:2.17.0-4.fc44 fedora 776.4 KiB fonts-filesystem noarch 1:5.0.0-2.fc44 fedora 0.0 B freetype x86_64 0:2.14.3-1.fc44 updates 918.3 KiB fribidi x86_64 0:1.0.16-4.fc44 fedora 190.0 KiB glib2 x86_64 0:2.88.4-1.fc44 updates 15.4 MiB google-noto-fonts-common noarch 0:20251201-2.fc44 fedora 17.7 KiB google-noto-sans-vf-fonts noarch 0:20251201-2.fc44 fedora 1.4 MiB graphite2 x86_64 0:1.3.14-20.fc44 fedora 191.5 KiB harfbuzz x86_64 0:14.1.0-2.fc44 updates 2.8 MiB jbigkit-libs x86_64 0:2.1-33.fc44 fedora 117.2 KiB lapack x86_64 0:3.12.0-11.fc44 fedora 16.4 MiB lcms2 x86_64 0:2.16-7.fc44 fedora 445.7 KiB libX11 x86_64 0:1.8.13-3.fc44 updates 1.3 MiB libX11-common noarch 0:1.8.13-3.fc44 updates 1.1 MiB libXau x86_64 0:1.0.12-4.fc44 fedora 72.8 KiB libXext x86_64 0:1.3.6-5.fc44 fedora 89.8 KiB libXrender x86_64 0:0.9.12-4.fc44 fedora 49.9 KiB libedit x86_64 0:3.1-59.20260512cvs.fc44 updates 248.3 KiB libgfortran x86_64 0:16.2.1-2.fc44 updates 3.4 MiB libimagequant x86_64 0:4.1.0-2.fc44 fedora 707.6 KiB libjpeg-turbo x86_64 0:3.1.3-1.fc44 fedora 818.2 KiB liblerc x86_64 0:4.0.0-10.fc44 fedora 647.9 KiB libpng x86_64 2:1.6.58-1.fc44 updates 249.6 KiB libqhull_r x86_64 1:8.0.2-8.fc44 fedora 491.2 KiB libquadmath x86_64 0:16.2.1-2.fc44 updates 325.9 KiB libraqm x86_64 0:0.10.1-4.fc44 fedora 32.5 KiB libsbml x86_64 0:5.20.5-100.fc44.biofedora copr_base 10.4 MiB libtiff x86_64 0:4.7.2-3.fc44 updates 648.6 KiB libwebp x86_64 0:1.6.0-3.fc44 fedora 968.0 KiB libxcb x86_64 0:1.17.0-7.fc44 fedora 1.1 MiB llvm13-libs x86_64 0:13.0.1-8.fc41 fedora 83.6 MiB lzo x86_64 0:2.10-16.fc44 fedora 174.8 KiB minizip-ng-compat x86_64 0:4.1.0-1.fc44 fedora 166.4 KiB mpdecimal x86_64 0:4.0.1-3.fc44 fedora 217.1 KiB openblas x86_64 0:0.3.29-2.fc43 fedora 111.7 KiB openblas-openmp x86_64 0:0.3.29-2.fc43 fedora 43.7 MiB openjpeg x86_64 0:2.5.4-3.fc44 fedora 464.2 KiB pixman x86_64 0:0.46.2-3.fc44 fedora 718.2 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.0.1-3.fc44 updates 1.2 MiB python-rpm-macros noarch 0:3.14-12.fc44 fedora 28.0 KiB python3 x86_64 0:3.14.8-1.fc44 updates 28.7 KiB python3-cairo x86_64 0:1.28.0-5.fc44 fedora 508.8 KiB python3-contourpy x86_64 0:1.4.0-1.fc44 updates 923.3 KiB python3-cycler noarch 0:0.11.0-20.fc44 fedora 37.8 KiB python3-dateutil noarch 1:2.9.0.post0-7.fc44 fedora 878.0 KiB python3-fonttools x86_64 0:4.62.1-1.fc44 updates 19.4 MiB python3-iniconfig noarch 0:2.3.0-2.fc44 fedora 49.8 KiB python3-kiwisolver x86_64 0:1.5.1-1.fc44 updates 157.8 KiB python3-libs x86_64 0:3.14.8-1.fc44 updates 44.1 MiB python3-matplotlib-data-fonts x86_64 0:3.10.8-2.fc44 fedora 7.9 MiB python3-numpy x86_64 1:2.4.6-1.fc44 updates 41.7 MiB python3-numpy-f2py x86_64 1:2.4.6-1.fc44 updates 2.1 MiB python3-olefile noarch 0:0.47-13.fc44 fedora 346.5 KiB python3-packaging noarch 0:25.0-8.fc44 fedora 607.4 KiB python3-pillow x86_64 0:12.3.0-1.fc44 updates 4.5 MiB python3-pluggy noarch 0:1.6.0-5.fc44 fedora 211.5 KiB python3-pygments noarch 0:2.19.1-9.fc44 fedora 11.3 MiB python3-pyparsing noarch 0:3.1.2-15.fc44 fedora 1.0 MiB python3-rpm-generators noarch 0:14-14.fc44 fedora 81.7 KiB python3-rpm-macros noarch 0:3.14-12.fc44 fedora 6.5 KiB python3-six noarch 0:1.17.0-8.fc44 fedora 118.0 KiB rr-libstruct x86_64 0:2.9.2-0.4.git7ff1f47.fc44 copr_base 254.9 KiB tzdata noarch 0:2026e-1.fc44 updates 1.3 MiB utf8proc x86_64 0:2.11.3-2.fc44 fedora 373.5 KiB xml-common noarch 0:0.6.3-68.fc44 fedora 78.4 KiB Transaction Summary: Installing: 82 packages Total size of inbound packages is 109 MiB. Need to download 27 MiB. After this operation, 462 MiB extra will be used (install 462 MiB, remove 0 B). [ 1/82] python3-pytest-0:8.4.2-2.fc44.n 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 2/82] python3-roadrunner-0:2.10.0-11. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 3/82] pyproject-rpm-macros-0:1.24.0-1 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 4/82] python3-devel-0:3.14.8-1.fc44.x 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 5/82] python3-libsbml-0:5.20.5-100.fc 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 6/82] python3-dateutil-1:2.9.0.post0- 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 7/82] python3-packaging-0:25.0-8.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 8/82] python3-iniconfig-0:2.3.0-2.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 9/82] python3-pluggy-0:1.6.0-5.fc44.n 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [10/82] python3-pygments-0:2.19.1-9.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [11/82] llvm13-libs-0:13.0.1-8.fc41.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [12/82] poco-foundation-0:1.14.1-3.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [13/82] poco-net-0:1.14.1-3.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [14/82] rr-libstruct-0:2.9.2-0.4.git7ff 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [15/82] python-rpm-macros-0:3.14-12.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [16/82] python3-rpm-macros-0:3.14-12.fc 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [17/82] python3-libs-0:3.14.8-1.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [18/82] minizip-ng-compat-0:4.1.0-1.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [19/82] libsbml-0:5.20.5-100.fc44.biofe 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [20/82] python3-six-0:1.17.0-8.fc44.noa 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [21/82] utf8proc-0:2.11.3-2.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [22/82] lapack-0:3.12.0-11.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [23/82] expat-0:2.8.5-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [24/82] mpdecimal-0:4.0.1-3.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [25/82] blas-0:3.12.0-11.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [26/82] python3-0:3.14.8-1.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [27/82] python3-numpy-1:2.4.6-1.fc44.x8 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [28/82] python3-numpy-f2py-1:2.4.6-1.fc 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [29/82] flexiblas-netlib-0:3.5.0-2.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [30/82] flexiblas-0:3.5.0-2.fc44.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [31/82] flexiblas-openblas-openmp-0:3.5 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [32/82] openblas-openmp-0:0.3.29-2.fc43 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [33/82] tzdata-0:2026e-1.fc44.noarch 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [34/82] libgfortran-0:16.2.1-2.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [35/82] openblas-0:0.3.29-2.fc43.x86_64 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [36/82] libedit-0:3.1-59.20260512cvs.fc 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [37/82] libquadmath-0:16.2.1-2.fc44.x86 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [38/82] python-pip-wheel-0:26.0.1-3.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [39/82] python3-rpm-generators-0:14-14. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [40/82] libqhull_r-1:8.0.2-8.fc44.x86_6 100% | 1.2 MiB/s | 206.7 KiB | 00m00s [41/82] python3-cycler-0:0.11.0-20.fc44 100% | 878.4 KiB/s | 22.0 KiB | 00m00s [42/82] dejavu-sans-fonts-0:2.37-29.fc4 100% | 5.1 MiB/s | 1.3 MiB | 00m00s [43/82] python3-pyparsing-0:3.1.2-15.fc 100% | 10.4 MiB/s | 286.8 KiB | 00m00s [44/82] fonts-filesystem-1:5.0.0-2.fc44 100% | 386.8 KiB/s | 8.9 KiB | 00m00s [45/82] python3-matplotlib-data-fonts-0 100% | 19.0 MiB/s | 2.3 MiB | 00m00s [46/82] python3-matplotlib-0:3.10.8-2.f 100% | 24.0 MiB/s | 7.9 MiB | 00m00s [47/82] python3-contourpy-0:1.4.0-1.fc4 100% | 664.4 KiB/s | 312.3 KiB | 00m00s [48/82] freetype-0:2.14.3-1.fc44.x86_64 100% | 891.5 KiB/s | 444.0 KiB | 00m00s [49/82] python3-kiwisolver-0:1.5.1-1.fc 100% | 713.8 KiB/s | 70.7 KiB | 00m00s [50/82] lcms2-0:2.16-7.fc44.x86_64 100% | 7.8 MiB/s | 191.4 KiB | 00m00s [51/82] libimagequant-0:4.1.0-2.fc44.x8 100% | 12.6 MiB/s | 323.0 KiB | 00m00s [52/82] libjpeg-turbo-0:3.1.3-1.fc44.x8 100% | 9.9 MiB/s | 243.4 KiB | 00m00s [53/82] libraqm-0:0.10.1-4.fc44.x86_64 100% | 954.3 KiB/s | 22.9 KiB | 00m00s [54/82] python3-pillow-0:12.3.0-1.fc44. 100% | 5.5 MiB/s | 1.1 MiB | 00m00s [55/82] libwebp-0:1.6.0-3.fc44.x86_64 100% | 12.9 MiB/s | 329.9 KiB | 00m00s [56/82] python3-fonttools-0:4.62.1-1.fc 100% | 4.7 MiB/s | 3.3 MiB | 00m01s [57/82] libxcb-0:1.17.0-7.fc44.x86_64 100% | 8.6 MiB/s | 238.0 KiB | 00m00s [58/82] openjpeg-0:2.5.4-3.fc44.x86_64 100% | 8.1 MiB/s | 198.1 KiB | 00m00s [59/82] python3-olefile-0:0.47-13.fc44. 100% | 3.2 MiB/s | 75.0 KiB | 00m00s [60/82] fribidi-0:1.0.16-4.fc44.x86_64 100% | 2.3 MiB/s | 53.8 KiB | 00m00s [61/82] libXau-0:1.0.12-4.fc44.x86_64 100% | 1.4 MiB/s | 33.7 KiB | 00m00s [62/82] python3-cairo-0:1.28.0-5.fc44.x 100% | 5.3 MiB/s | 130.0 KiB | 00m00s [63/82] fontconfig-0:2.17.0-4.fc44.x86_ 100% | 10.9 MiB/s | 278.2 KiB | 00m00s [64/82] libXext-0:1.3.6-5.fc44.x86_64 100% | 1.7 MiB/s | 40.7 KiB | 00m00s [65/82] libXrender-0:0.9.12-4.fc44.x86_ 100% | 1.1 MiB/s | 27.9 KiB | 00m00s [66/82] lzo-0:2.10-16.fc44.x86_64 100% | 3.0 MiB/s | 69.7 KiB | 00m00s [67/82] pixman-0:0.46.2-3.fc44.x86_64 100% | 11.6 MiB/s | 297.4 KiB | 00m00s [68/82] cairo-0:1.18.6-1.fc44.x86_64 100% | 7.8 MiB/s | 757.6 KiB | 00m00s [69/82] default-fonts-core-sans-0:4.3-1 100% | 1.2 MiB/s | 29.2 KiB | 00m00s [70/82] xml-common-0:0.6.3-68.fc44.noar 100% | 1.3 MiB/s | 31.1 KiB | 00m00s [71/82] abattis-cantarell-vf-fonts-0:0. 100% | 4.9 MiB/s | 120.4 KiB | 00m00s [72/82] google-noto-sans-vf-fonts-0:202 100% | 18.8 MiB/s | 614.9 KiB | 00m00s [73/82] google-noto-fonts-common-0:2025 100% | 738.9 KiB/s | 17.7 KiB | 00m00s [74/82] graphite2-0:1.3.14-20.fc44.x86_ 100% | 3.9 MiB/s | 96.5 KiB | 00m00s [75/82] libX11-common-0:1.8.13-3.fc44.n 100% | 2.7 MiB/s | 175.3 KiB | 00m00s [76/82] harfbuzz-0:14.1.0-2.fc44.x86_64 100% | 11.3 MiB/s | 1.1 MiB | 00m00s [77/82] jbigkit-libs-0:2.1-33.fc44.x86_ 100% | 2.2 MiB/s | 54.3 KiB | 00m00s [78/82] liblerc-0:4.0.0-10.fc44.x86_64 100% | 9.2 MiB/s | 225.9 KiB | 00m00s [79/82] libtiff-0:4.7.2-3.fc44.x86_64 100% | 3.0 MiB/s | 233.5 KiB | 00m00s [80/82] libX11-0:1.8.13-3.fc44.x86_64 100% | 3.7 MiB/s | 680.0 KiB | 00m00s [81/82] libpng-2:1.6.58-1.fc44.x86_64 100% | 2.0 MiB/s | 129.5 KiB | 00m00s [82/82] glib2-0:2.88.4-1.fc44.x86_64 100% | 28.9 MiB/s | 3.1 MiB | 00m00s -------------------------------------------------------------------------------- [82/82] Total 100% | 17.9 MiB/s | 27.1 MiB | 00m02s Running transaction [ 1/84] Verify package files 100% | 200.0 B/s | 82.0 B | 00m00s [ 2/84] Prepare transaction 100% | 788.0 B/s | 82.0 B | 00m00s [ 3/84] Installing libgfortran-0:16.2.1 100% | 340.2 MiB/s | 3.4 MiB | 00m00s [ 4/84] Installing fonts-filesystem-1:5 100% | 0.0 B/s | 788.0 B | 00m00s [ 5/84] Installing python-rpm-macros-0: 100% | 0.0 B/s | 28.9 KiB | 00m00s [ 6/84] Installing python3-rpm-macros-0 100% | 6.6 MiB/s | 6.8 KiB | 00m00s [ 7/84] Installing blas-0:3.12.0-11.fc4 100% | 185.1 MiB/s | 1.5 MiB | 00m00s [ 8/84] Installing libpng-2:1.6.58-1.fc 100% | 49.0 MiB/s | 250.9 KiB | 00m00s [ 9/84] Installing tzdata-0:2026e-1.fc4 100% | 54.4 MiB/s | 1.5 MiB | 00m00s [10/84] Installing libwebp-0:1.6.0-3.fc 100% | 316.4 MiB/s | 972.1 KiB | 00m00s [11/84] Installing libjpeg-turbo-0:3.1. 100% | 400.3 MiB/s | 819.9 KiB | 00m00s [12/84] Installing minizip-ng-compat-0: 100% | 163.3 MiB/s | 167.2 KiB | 00m00s [13/84] Installing libsbml-0:5.20.5-100 100% | 230.3 MiB/s | 10.4 MiB | 00m00s [14/84] Installing lapack-0:3.12.0-11.f 100% | 115.9 MiB/s | 17.6 MiB | 00m00s [15/84] Installing rr-libstruct-0:2.9.2 100% | 249.7 MiB/s | 255.7 KiB | 00m00s [16/84] Installing pyproject-rpm-macros 100% | 167.4 MiB/s | 171.5 KiB | 00m00s [17/84] Installing dejavu-sans-fonts-0: 100% | 423.7 MiB/s | 5.5 MiB | 00m00s [18/84] Installing abattis-cantarell-vf 100% | 189.9 MiB/s | 194.4 KiB | 00m00s [19/84] Installing glib2-0:2.88.4-1.fc4 100% | 314.0 MiB/s | 15.4 MiB | 00m00s [20/84] Installing python-pip-wheel-0:2 100% | 611.8 MiB/s | 1.2 MiB | 00m00s [21/84] Installing liblerc-0:4.0.0-10.f 100% | 317.1 MiB/s | 649.4 KiB | 00m00s [22/84] Installing jbigkit-libs-0:2.1-3 100% | 116.4 MiB/s | 119.2 KiB | 00m00s [23/84] Installing libtiff-0:4.7.2-3.fc 100% | 317.8 MiB/s | 650.8 KiB | 00m00s [24/84] Installing libquadmath-0:16.2.1 100% | 159.8 MiB/s | 327.2 KiB | 00m00s [25/84] Installing libX11-common-0:1.8. 100% | 169.3 MiB/s | 1.2 MiB | 00m00s [26/84] Installing graphite2-0:1.3.14-2 100% | 14.5 MiB/s | 193.6 KiB | 00m00s [27/84] Installing freetype-0:2.14.3-1. 100% | 299.5 MiB/s | 920.0 KiB | 00m00s [28/84] Installing harfbuzz-0:14.1.0-2. 100% | 351.6 MiB/s | 2.8 MiB | 00m00s [29/84] Installing libedit-0:3.1-59.202 100% | 244.1 MiB/s | 250.0 KiB | 00m00s [30/84] Installing llvm13-libs-0:13.0.1 100% | 457.0 MiB/s | 83.6 MiB | 00m00s [31/84] Installing openblas-0:0.3.29-2. 100% | 110.8 MiB/s | 113.5 KiB | 00m00s [32/84] Installing openblas-openmp-0:0. 100% | 615.3 MiB/s | 43.7 MiB | 00m00s [33/84] Installing flexiblas-netlib-0:3 100% | 320.2 MiB/s | 16.3 MiB | 00m00s [34/84] Installing flexiblas-0:3.5.0-2. 100% | 0.0 B/s | 39.2 KiB | 00m00s [35/84] Installing flexiblas-openblas-o 100% | 0.0 B/s | 39.9 KiB | 00m00s [36/84] Installing google-noto-fonts-co 100% | 0.0 B/s | 18.5 KiB | 00m00s [37/84] Installing google-noto-sans-vf- 100% | 347.8 MiB/s | 1.4 MiB | 00m00s [38/84] Installing default-fonts-core-s 100% | 3.0 MiB/s | 18.2 KiB | 00m00s [39/84] Installing xml-common-0:0.6.3-6 100% | 79.2 MiB/s | 81.1 KiB | 00m00s [40/84] Installing fontconfig-0:2.17.0- 100% | 766.6 KiB/s | 795.8 KiB | 00m01s [41/84] Installing pixman-0:0.46.2-3.fc 100% | 234.1 MiB/s | 719.3 KiB | 00m00s [42/84] Installing lzo-0:2.10-16.fc44.x 100% | 172.3 MiB/s | 176.4 KiB | 00m00s [43/84] Installing libXau-0:1.0.12-4.fc 100% | 72.6 MiB/s | 74.3 KiB | 00m00s [44/84] Installing libxcb-0:1.17.0-7.fc 100% | 215.5 MiB/s | 1.1 MiB | 00m00s [45/84] Installing libX11-0:1.8.13-3.fc 100% | 336.0 MiB/s | 1.3 MiB | 00m00s [46/84] Installing libXext-0:1.3.6-5.fc 100% | 88.9 MiB/s | 91.1 KiB | 00m00s [47/84] Installing libXrender-0:0.9.12- 100% | 0.0 B/s | 51.2 KiB | 00m00s [48/84] Installing cairo-0:1.18.6-1.fc4 100% | 365.6 MiB/s | 1.8 MiB | 00m00s [49/84] Installing fribidi-0:1.0.16-4.f 100% | 13.4 MiB/s | 192.5 KiB | 00m00s [50/84] Installing libraqm-0:0.10.1-4.f 100% | 0.0 B/s | 33.6 KiB | 00m00s [51/84] Installing openjpeg-0:2.5.4-3.f 100% | 227.6 MiB/s | 466.1 KiB | 00m00s [52/84] Installing libimagequant-0:4.1. 100% | 346.3 MiB/s | 709.2 KiB | 00m00s [53/84] Installing lcms2-0:2.16-7.fc44. 100% | 218.4 MiB/s | 447.3 KiB | 00m00s [54/84] Installing mpdecimal-0:4.0.1-3. 100% | 213.5 MiB/s | 218.6 KiB | 00m00s [55/84] Installing expat-0:2.8.5-1.fc44 100% | 17.7 MiB/s | 344.3 KiB | 00m00s [56/84] Installing python3-libs-0:3.14. 100% | 347.5 MiB/s | 44.5 MiB | 00m00s [57/84] Installing python3-0:3.14.8-1.f 100% | 2.1 MiB/s | 30.4 KiB | 00m00s [58/84] Installing python3-numpy-f2py-1 100% | 80.8 MiB/s | 2.2 MiB | 00m00s [59/84] Installing python3-numpy-1:2.4. 100% | 353.1 MiB/s | 42.0 MiB | 00m00s [60/84] Installing python3-packaging-0: 100% | 201.8 MiB/s | 619.9 KiB | 00m00s [61/84] Installing python3-rpm-generato 100% | 81.0 MiB/s | 82.9 KiB | 00m00s [62/84] Installing python3-contourpy-0: 100% | 228.6 MiB/s | 936.4 KiB | 00m00s [63/84] Installing python3-cycler-0:0.1 100% | 39.3 MiB/s | 40.3 KiB | 00m00s [64/84] Installing python3-pyparsing-0: 100% | 343.1 MiB/s | 1.0 MiB | 00m00s [65/84] Installing python3-iniconfig-0: 100% | 52.9 MiB/s | 54.1 KiB | 00m00s [66/84] Installing python3-pluggy-0:1.6 100% | 53.2 MiB/s | 217.9 KiB | 00m00s [67/84] Installing python3-pygments-0:2 100% | 229.7 MiB/s | 11.5 MiB | 00m00s [68/84] Installing python3-six-0:1.17.0 100% | 117.5 MiB/s | 120.3 KiB | 00m00s [69/84] Installing python3-dateutil-1:2 100% | 145.1 MiB/s | 891.5 KiB | 00m00s [70/84] Installing python3-fonttools-0: 100% | 377.0 MiB/s | 19.6 MiB | 00m00s [71/84] Installing python3-kiwisolver-0 100% | 158.1 MiB/s | 161.9 KiB | 00m00s [72/84] Installing python3-olefile-0:0. 100% | 170.8 MiB/s | 349.8 KiB | 00m00s [73/84] Installing python3-pillow-0:12. 100% | 324.0 MiB/s | 4.5 MiB | 00m00s [74/84] Installing python3-cairo-0:1.28 100% | 250.2 MiB/s | 512.3 KiB | 00m00s [75/84] Installing utf8proc-0:2.11.3-2. 100% | 366.1 MiB/s | 374.9 KiB | 00m00s [76/84] Installing poco-foundation-0:1. 100% | 377.1 MiB/s | 2.3 MiB | 00m00s [77/84] Installing poco-net-0:1.14.1-3. 100% | 363.2 MiB/s | 1.5 MiB | 00m00s [78/84] Installing python3-matplotlib-d 100% | 395.7 MiB/s | 7.9 MiB | 00m00s [79/84] Installing libqhull_r-1:8.0.2-8 100% | 120.1 MiB/s | 492.0 KiB | 00m00s [80/84] Installing python3-matplotlib-0 100% | 416.2 MiB/s | 32.0 MiB | 00m00s [81/84] Installing python3-roadrunner-0 100% | 416.4 MiB/s | 12.1 MiB | 00m00s [82/84] Installing python3-pytest-0:8.4 100% | 371.7 MiB/s | 22.7 MiB | 00m00s [83/84] Installing python3-devel-0:3.14 100% | 95.5 MiB/s | 2.0 MiB | 00m00s [84/84] Installing python3-libsbml-0:5. 100% | 232.3 MiB/s | 34.4 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.fc44.src.rpm Updating and loading repositories: updates 100% | 101.7 KiB/s | 23.1 KiB | 00m00s fedora 100% | 104.2 KiB/s | 23.8 KiB | 00m00s Additional repo copr_mhough_neurofedor 100% | 10.6 KiB/s | 1.5 KiB | 00m00s Copr repository 100% | 10.5 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Nothing to do. Package "pyproject-rpm-macros-1.24.0-1.fc44.noarch" is already installed. Package "python3-devel-3.14.8-1.fc44.x86_64" is already installed. Package "python3-libsbml-5.20.5-100.fc44.biofedora.x86_64" is already installed. Package "python3-matplotlib-3.10.8-2.fc44.x86_64" is already installed. Package "python3-pytest-8.4.2-2.fc44.noarch" is already installed. Package "python3-roadrunner-2.10.0-11.fc44.x86_64" is already installed. Finish: build setup for python-sbmlutils-0.17.0-1.fc44.src.rpm Start: rpmbuild python-sbmlutils-0.17.0-1.fc44.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.yfkukI Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.GYPD5y + 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/lib/rpm/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.2DZ9IN + 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=py314 + FEDORA=44 + 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.fc44.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc44.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.fc44.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.fc44.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: updates 100% | 100.0 KiB/s | 23.1 KiB | 00m00s fedora 100% | 102.9 KiB/s | 23.8 KiB | 00m00s Additional repo copr_mhough_neurofedor 100% | 10.0 KiB/s | 1.5 KiB | 00m00s Copr repository 100% | 10.0 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc44.noarch" is already installed. Package "python3-devel-3.14.8-1.fc44.x86_64" is already installed. Package "python3-libsbml-5.20.5-100.fc44.biofedora.x86_64" is already installed. Package "python3-matplotlib-3.10.8-2.fc44.x86_64" is already installed. Package "python3-pytest-8.4.2-2.fc44.noarch" is already installed. Package "python3-roadrunner-2.10.0-11.fc44.x86_64" is already installed. Package "python3-packaging-25.0-8.fc44.noarch" is already installed. Package Arch Version Repository Size Installing: python3-hatchling noarch 0:1.31.0-1.fc44 updates 681.6 KiB python3-pip noarch 0:26.0.1-3.fc44 updates 11.5 MiB Installing dependencies: python3-pathspec noarch 0:1.0.3-2.fc44 fedora 372.4 KiB python3-trove-classifiers noarch 0:2026.1.14.14-2.fc44 fedora 111.9 KiB Transaction Summary: Installing: 4 packages Total size of inbound packages is 3 MiB. Need to download 0 B. After this operation, 13 MiB extra will be used (install 13 MiB, remove 0 B). [1/4] python3-hatchling-0:1.31.0-1.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [2/4] python3-pip-0:26.0.1-3.fc44.noarc 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [3/4] python3-pathspec-0:1.0.3-2.fc44.n 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [4/4] python3-trove-classifiers-0:2026. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded -------------------------------------------------------------------------------- [4/4] Total 100% | 0.0 B/s | 0.0 B | 00m00s Running transaction [1/6] Verify package files 100% | 363.0 B/s | 4.0 B | 00m00s [2/6] Prepare transaction 100% | 166.0 B/s | 4.0 B | 00m00s [3/6] Installing python3-trove-classifi 100% | 8.1 MiB/s | 115.7 KiB | 00m00s [4/6] Installing python3-pathspec-0:1.0 100% | 96.3 MiB/s | 394.6 KiB | 00m00s [5/6] Installing python3-hatchling-0:1. 100% | 34.0 MiB/s | 730.8 KiB | 00m00s [6/6] Installing python3-pip-0:26.0.1-3 100% | 150.5 MiB/s | 11.7 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.1aLMhu + 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=py314 + FEDORA=44 + 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.fc44.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc44.x86_64-pyproject-dep-overrides Handling hatchling from build-system.requires Requirement satisfied: hatchling (installed: hatchling 1.31.0) 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.4.6) 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.fc44.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.fc44.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: updates 100% | 103.1 KiB/s | 23.1 KiB | 00m00s fedora 100% | 106.1 KiB/s | 23.8 KiB | 00m00s Additional repo copr_mhough_neurofedor 100% | 13.6 KiB/s | 1.5 KiB | 00m00s Copr repository 100% | 13.5 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc44.noarch" is already installed. Package "python3-devel-3.14.8-1.fc44.x86_64" is already installed. Package "python3-libsbml-5.20.5-100.fc44.biofedora.x86_64" is already installed. Package "python3-matplotlib-3.10.8-2.fc44.x86_64" is already installed. Package "python3-pytest-8.4.2-2.fc44.noarch" is already installed. Package "python3-roadrunner-2.10.0-11.fc44.x86_64" is already installed. Package "python3-hatchling-1.31.0-1.fc44.noarch" is already installed. Package "python3-numpy-1:2.4.6-1.fc44.x86_64" is already installed. Package "python3-packaging-25.0-8.fc44.noarch" is already installed. Package "python3-pip-26.0.1-3.fc44.noarch" is already installed. Package Arch Version Repository Size Installing: python3-antimony x86_64 0:3.2.1-1.fc44 copr_base 2.1 MiB python3-certifi noarch 0:2026.01.04-1.fc44 fedora 7.4 KiB python3-jinja2 noarch 0:3.1.6-7.fc44 fedora 3.1 MiB python3-lxml x86_64 0:6.1.1-1.fc44 updates 5.8 MiB python3-markdown-it-py noarch 0:3.0.0-14.fc44 fedora 541.5 KiB python3-openpyxl noarch 0:3.1.5-5.fc44 fedora 1.9 MiB python3-pandas x86_64 0:2.3.3-3.fc44 fedora 41.7 MiB python3-pint noarch 0:0.25.2-2.fc44 fedora 3.4 MiB python3-pymetadata noarch 0:0.8.2-1.fc44 copr_base 2.9 MiB python3-requests noarch 0:2.33.1-1.fc44 updates 477.3 KiB python3-rich noarch 0:14.3.2-1.fc44 fedora 3.4 MiB python3-sbmlode noarch 0:0.3.1-1.fc44 copr_base 895.1 KiB python3-xmltodict noarch 0:0.14.2-5.fc44 fedora 56.0 KiB Installing dependencies: libsbmlnetwork x86_64 0:0.5.12-2.fc44 copr_base 3.5 MiB libxslt x86_64 0:1.1.43-6.fc44 fedora 471.8 KiB python3-Bottleneck x86_64 0:1.6.0-2.fc44 fedora 573.3 KiB python3-annotated-types noarch 0:0.7.0-9.fc44 fedora 85.1 KiB python3-charset-normalizer noarch 0:3.4.4-2.fc44 fedora 356.2 KiB python3-et_xmlfile noarch 0:2.0.0-7.fc44 fedora 100.3 KiB python3-flexcache noarch 0:0.3-11.fc44 fedora 57.0 KiB python3-flexparser noarch 0:0.4-7.fc44 fedora 263.5 KiB python3-idna noarch 0:3.18-1.fc44 updates 522.3 KiB python3-markupsafe x86_64 0:3.0.2-7.fc44 fedora 61.4 KiB python3-mdurl noarch 0:0.1.2-14.fc44 fedora 44.0 KiB python3-numexpr x86_64 0:2.14.1-1.fc44 fedora 859.7 KiB python3-platformdirs noarch 0:4.9.1-1.fc44 fedora 236.5 KiB python3-pydantic noarch 0:2.12.5-4.fc44 updates 5.1 MiB python3-pydantic-core x86_64 0:2.41.5-11.fc44 updates 5.4 MiB python3-pytz noarch 0:2026.5-1.fc44 updates 228.2 KiB python3-typing-extensions noarch 0:4.16.0-4.fc44 updates 552.0 KiB python3-typing-inspection noarch 0:0.4.4-1.fc44 updates 93.4 KiB python3-urllib3 noarch 0:2.8.0-3.fc44 updates 1.2 MiB Transaction Summary: Installing: 32 packages Total size of inbound packages is 18 MiB. Need to download 8 MiB. After this operation, 86 MiB extra will be used (install 86 MiB, remove 0 B). [ 1/32] python3-jinja2-0:3.1.6-7.fc44.n 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 2/32] python3-markdown-it-py-0:3.0.0- 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 3/32] python3-pandas-0:2.3.3-3.fc44.x 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 4/32] python3-antimony-0:3.2.1-1.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 5/32] python3-requests-0:2.33.1-1.fc4 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 6/32] python3-markupsafe-0:3.0.2-7.fc 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 7/32] python3-mdurl-0:0.1.2-14.fc44.n 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 8/32] python3-Bottleneck-0:1.6.0-2.fc 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [ 9/32] python3-numexpr-0:2.14.1-1.fc44 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [10/32] python3-platformdirs-0:4.9.1-1. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [11/32] libsbmlnetwork-0:0.5.12-2.fc44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [12/32] python3-charset-normalizer-0:3. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [13/32] python3-urllib3-0:2.8.0-3.fc44. 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [14/32] python3-pytz-0:2026.5-1.fc44.no 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [15/32] python3-idna-0:3.18-1.fc44.noar 100% | 0.0 B/s | 0.0 B | 00m00s >>> Already downloaded [16/32] python3-certifi-0:2026.01.04-1. 100% | 80.7 KiB/s | 14.9 KiB | 00m00s [17/32] python3-openpyxl-0:3.1.5-5.fc44 100% | 1.2 MiB/s | 616.1 KiB | 00m01s [18/32] python3-pint-0:0.25.2-2.fc44.no 100% | 1.7 MiB/s | 740.8 KiB | 00m00s [19/32] python3-lxml-0:6.1.1-1.fc44.x86 100% | 2.7 MiB/s | 1.7 MiB | 00m01s [20/32] python3-rich-0:14.3.2-1.fc44.no 100% | 5.1 MiB/s | 663.8 KiB | 00m00s [21/32] python3-xmltodict-0:0.14.2-5.fc 100% | 158.8 KiB/s | 26.7 KiB | 00m00s [22/32] python3-sbmlode-0:0.3.1-1.fc44. 100% | 931.1 KiB/s | 230.9 KiB | 00m00s [23/32] python3-pymetadata-0:0.8.2-1.fc 100% | 1.3 MiB/s | 375.0 KiB | 00m00s [24/32] python3-et_xmlfile-0:2.0.0-7.fc 100% | 23.4 KiB/s | 45.4 KiB | 00m02s [25/32] python3-flexcache-0:0.3-11.fc44 100% | 14.4 KiB/s | 27.2 KiB | 00m02s [26/32] libxslt-0:1.1.43-6.fc44.x86_64 100% | 96.2 KiB/s | 192.7 KiB | 00m02s [27/32] python3-annotated-types-0:0.7.0 100% | 505.8 KiB/s | 31.4 KiB | 00m00s [28/32] python3-flexparser-0:0.4-7.fc44 100% | 858.5 KiB/s | 54.9 KiB | 00m00s [29/32] python3-pydantic-0:2.12.5-4.fc4 100% | 11.1 MiB/s | 1.0 MiB | 00m00s [30/32] python3-typing-inspection-0:0.4 100% | 318.1 KiB/s | 33.7 KiB | 00m00s [31/32] python3-typing-extensions-0:4.1 100% | 858.1 KiB/s | 114.1 KiB | 00m00s [32/32] python3-pydantic-core-0:2.41.5- 100% | 6.8 MiB/s | 1.7 MiB | 00m00s -------------------------------------------------------------------------------- [32/32] Total 100% | 2.4 MiB/s | 7.5 MiB | 00m03s Running transaction [ 1/34] Verify package files 100% | 463.0 B/s | 32.0 B | 00m00s [ 2/34] Prepare transaction 100% | 666.0 B/s | 32.0 B | 00m00s [ 3/34] Installing python3-typing-exten 100% | 270.6 MiB/s | 554.3 KiB | 00m00s [ 4/34] Installing python3-idna-0:3.18- 100% | 34.5 MiB/s | 530.2 KiB | 00m00s [ 5/34] Installing python3-urllib3-0:2. 100% | 235.9 MiB/s | 1.2 MiB | 00m00s [ 6/34] Installing python3-flexcache-0: 100% | 59.2 MiB/s | 60.6 KiB | 00m00s [ 7/34] Installing python3-flexparser-0 100% | 260.8 MiB/s | 267.1 KiB | 00m00s [ 8/34] Installing python3-pydantic-cor 100% | 382.5 MiB/s | 5.4 MiB | 00m00s [ 9/34] Installing python3-typing-inspe 100% | 95.2 MiB/s | 97.5 KiB | 00m00s [10/34] Installing python3-pytz-0:2026. 100% | 228.1 MiB/s | 233.6 KiB | 00m00s [11/34] Installing python3-annotated-ty 100% | 86.2 MiB/s | 88.2 KiB | 00m00s [12/34] Installing python3-pydantic-0:2 100% | 342.2 MiB/s | 5.1 MiB | 00m00s [13/34] Installing python3-charset-norm 100% | 25.6 MiB/s | 366.4 KiB | 00m00s [14/34] Installing python3-requests-0:2 100% | 239.0 MiB/s | 489.5 KiB | 00m00s [15/34] Installing libsbmlnetwork-0:0.5 100% | 504.3 MiB/s | 3.5 MiB | 00m00s [16/34] Installing python3-platformdirs 100% | 237.7 MiB/s | 243.4 KiB | 00m00s [17/34] Installing python3-numexpr-0:2. 100% | 212.7 MiB/s | 871.4 KiB | 00m00s [18/34] Installing python3-Bottleneck-0 100% | 145.5 MiB/s | 596.0 KiB | 00m00s [19/34] Installing python3-mdurl-0:0.1. 100% | 48.3 MiB/s | 49.4 KiB | 00m00s [20/34] Installing python3-markdown-it- 100% | 31.8 MiB/s | 585.7 KiB | 00m00s [21/34] Installing python3-rich-0:14.3. 100% | 316.0 MiB/s | 3.5 MiB | 00m00s [22/34] Installing libxslt-0:1.1.43-6.f 100% | 33.1 MiB/s | 474.9 KiB | 00m00s [23/34] Installing python3-lxml-0:6.1.1 100% | 324.0 MiB/s | 5.8 MiB | 00m00s [24/34] Installing python3-et_xmlfile-0 100% | 103.0 MiB/s | 105.5 KiB | 00m00s [25/34] Installing python3-markupsafe-0 100% | 64.1 MiB/s | 65.7 KiB | 00m00s [26/34] Installing python3-jinja2-0:3.1 100% | 386.5 MiB/s | 3.1 MiB | 00m00s [27/34] Installing python3-certifi-0:20 100% | 10.9 MiB/s | 11.2 KiB | 00m00s [28/34] Installing python3-pymetadata-0 100% | 423.3 MiB/s | 3.0 MiB | 00m00s [29/34] Installing python3-sbmlode-0:0. 100% | 177.8 MiB/s | 910.5 KiB | 00m00s [30/34] Installing python3-openpyxl-0:3 100% | 125.3 MiB/s | 2.0 MiB | 00m00s [31/34] Installing python3-pandas-0:2.3 100% | 403.3 MiB/s | 41.9 MiB | 00m00s [32/34] Installing python3-pint-0:0.25. 100% | 138.6 MiB/s | 3.5 MiB | 00m00s [33/34] Installing python3-antimony-0:3 100% | 354.0 MiB/s | 2.1 MiB | 00m00s [34/34] Installing python3-xmltodict-0: 100% | 2.5 MiB/s | 58.5 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.PAe7TU + 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=py314 + FEDORA=44 + 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.fc44.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc44.x86_64-pyproject-dep-overrides Handling hatchling from build-system.requires Requirement satisfied: hatchling (installed: hatchling 1.31.0) 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.1) 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 3.0.0) Handling numpy>=2.2.2 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: numpy>=2.2.2 (installed: numpy 2.4.6) 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 2.3.3) Handling pint>=0.25 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: pint>=0.25 (installed: pint 0.25.2) 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.33.1) Handling rich>=13.0.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: rich>=13.0.0 (installed: rich 14.3.2) 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.fc44.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.fc44.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: updates 100% | 99.6 KiB/s | 23.1 KiB | 00m00s fedora 100% | 102.4 KiB/s | 23.8 KiB | 00m00s Additional repo copr_mhough_neurofedor 100% | 10.5 KiB/s | 1.5 KiB | 00m00s Copr repository 100% | 10.4 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc44.noarch" is already installed. Package "python3-devel-3.14.8-1.fc44.x86_64" is already installed. Package "python3-libsbml-5.20.5-100.fc44.biofedora.x86_64" is already installed. Package "python3-matplotlib-3.10.8-2.fc44.x86_64" is already installed. Package "python3-pytest-8.4.2-2.fc44.noarch" is already installed. Package "python3-roadrunner-2.10.0-11.fc44.x86_64" is already installed. Package "python3-antimony-3.2.1-1.fc44.x86_64" is already installed. Package "python3-certifi-2026.01.04-1.fc44.noarch" is already installed. Package "python3-hatchling-1.31.0-1.fc44.noarch" is already installed. Package "python3-jinja2-3.1.6-7.fc44.noarch" is already installed. Package "python3-lxml-6.1.1-1.fc44.x86_64" is already installed. Package "python3-markdown-it-py-3.0.0-14.fc44.noarch" is already installed. Package "python3-numpy-1:2.4.6-1.fc44.x86_64" is already installed. Package "python3-openpyxl-3.1.5-5.fc44.noarch" is already installed. Package "python3-packaging-25.0-8.fc44.noarch" is already installed. Package "python3-pandas-2.3.3-3.fc44.x86_64" is already installed. Package "python3-pint-0.25.2-2.fc44.noarch" is already installed. Package "python3-pip-26.0.1-3.fc44.noarch" is already installed. Package "python3-pymetadata-0.8.2-1.fc44.noarch" is already installed. Package "python3-requests-2.33.1-1.fc44.noarch" is already installed. Package "python3-rich-14.3.2-1.fc44.noarch" is already installed. Package "python3-sbmlode-0.3.1-1.fc44.noarch" is already installed. Package "python3-xmltodict-0.14.2-5.fc44.noarch" is already installed. Nothing to do. 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.UX7M53 + 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=py314 + FEDORA=44 + 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.fc44.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc44.x86_64-pyproject-dep-overrides Handling hatchling from build-system.requires Requirement satisfied: hatchling (installed: hatchling 1.31.0) 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.1) 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 3.0.0) Handling numpy>=2.2.2 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: numpy>=2.2.2 (installed: numpy 2.4.6) 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 2.3.3) Handling pint>=0.25 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: pint>=0.25 (installed: pint 0.25.2) 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.33.1) Handling rich>=13.0.0 from hook generated metadata: Requires-Dist (sbmlutils) Requirement satisfied: rich>=13.0.0 (installed: rich 14.3.2) 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.fc44.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.ClsxTp + 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=3633279 sha256=436ce409b1f1bae4f6afe66c534b837077da714b185049c3d57f98bc2ca084fa Stored in directory: /builddir/.cache/pip/wheels/b8/c9/e2/df1ef8885d97c39647586eef9f2cba9beca56d30bd6d8cd270 Successfully built sbmlutils + RPM_EC=0 ++ jobs -p + exit 0 Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.XJ5Jbt + 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.0.1 from /usr/lib/python3.14/site-packages/pip (python 3.14) 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.fc44.x86_64-pyproject-ghost-distinfo + site_dirs=() + '[' -d /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages ']' + site_dirs+=("/usr/lib/python3.14/site-packages") + '[' /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib64/python3.14/site-packages '!=' /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages ']' + '[' -d /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib64/python3.14/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.14/site-packages/sbmlutils-0.17.0.dist-info' +++ basename /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/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.14/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.14/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.14/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.fc44.x86_64-pyproject-record + rm -fv /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils-0.17.0.dist-info/RECORD removed '/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils-0.17.0.dist-info/RECORD' + rm -fv /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils-0.17.0.dist-info/REQUESTED removed '/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/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.fc44.x86_64-pyproject-dep-overrides ']' ++ wc -l /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc44.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.fc44.x86_64-pyproject-files --output-modules /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc44.x86_64-pyproject-modules --buildroot /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT --sitelib /usr/lib/python3.14/site-packages --sitearch /usr/lib64/python3.14/site-packages --python-version 3.14 --pyproject-record /builddir/build/BUILD/python-sbmlutils-0.17.0-build/python-sbmlutils-0.17.0-1.fc44.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.14/site-packages/sbmlutils/resources/xslt/pmml2tex/run is executable but has no shebang, removing executable bit *** WARNING: ./usr/lib/python3.14/site-packages/sbmlutils/resources/xslt/pmml2tex/pmml2texfrag.xsl is executable but has no shebang, removing executable bit *** WARNING: ./usr/lib/python3.14/site-packages/sbmlutils/resources/xslt/pmml2tex/pmml2tex.xsl is executable but has no shebang, removing executable bit *** WARNING: ./usr/lib/python3.14/site-packages/sbmlutils/resources/xslt/pmml2tex/pmml-new.sty is executable but has no shebang, removing executable bit *** WARNING: ./usr/lib/python3.14/site-packages/sbmlutils/resources/xslt/pmml2tex/mml2tex.xsl is executable but has no shebang, removing executable bit *** WARNING: ./usr/lib/python3.14/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.14 using python3.14 + /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.14/site-packages/sbmlutils/__pycache__/utils.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/__pycache__/notes.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/__pycache__/log.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/__pycache__/parser.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/__pycache__/reaction_equation.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/__pycache__/console.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/__pycache__/cytoscape.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/__pycache__/_antimony.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/resources/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/__pycache__/biomodels.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/__pycache__/validation.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/report/__pycache__/units.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/report/__pycache__/sbmlreport.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/report/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/__pycache__/miriam.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/report/__pycache__/mathml.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/__pycache__/validator.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/manipulation/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/manipulation/__pycache__/merge.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/layout/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/io/__pycache__/sbml.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/layout/__pycache__/layout.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/io/__pycache__/antimony.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/io/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/fbc/__pycache__/fbc.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/__pycache__/annotator.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/fbc/__pycache__/cobra.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/fbc/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/io/__pycache__/files.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/__pycache__/fbc.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/report/__pycache__/sbmlinfo.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/__pycache__/distrib.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/__pycache__/model.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/__pycache__/comp.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/distrib/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/__pycache__/_core.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/__pycache__/units.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/data/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/converters/__pycache__/xpp_helpers.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/data/__pycache__/interpolation.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/converters/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/converters/__pycache__/copasi.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/converters/ode/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/comp/__pycache__/flatten.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/comp/__pycache__/comp.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/data/__pycache__/_driving.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/comp/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/converters/__pycache__/xpp.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/__pycache__/core_elements.cpython-314.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 108 files, linked 7 files, 0 errors sum of sizes of linked files: 49769 bytes Executing(%check): /bin/sh -e /var/tmp/rpm-tmp.CvMNUK + 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.14/site-packages:/builddir/build/BUILD/python-sbmlutils-0.17.0-build/BUILDROOT/usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:802: in create_sbml child.create_sbml(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:523: in create_sbml self._set_fields(span, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:534: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:210: in _set_fields super()._set_fields(sbase, None) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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 203, in _run_module_as_main E File "", line 88, 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 203, in _run_module_as_main E File "", line 88, 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 203, in _run_module_as_main E File "", line 88, 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 203, in _run_module_as_main E File "", line 88, 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 203, in _run_module_as_main E File "", line 88, 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 203, in _run_module_as_main E File "", line 88, 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 203, in _run_module_as_main E File "", line 88, 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 203, in _run_module_as_main E File "", line 88, 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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1773: in create_model doc = annotator.annotate_sbml_doc( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:276: in annotate_sbml_doc annotator.annotate_model() ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:429: in annotate_model self._annotate_elements(elements, a) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:523: in _annotate_elements annotation = Annotation( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1773: in create_model doc = annotator.annotate_sbml_doc( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:276: in annotate_sbml_doc annotator.annotate_model() ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:429: in annotate_model self._annotate_elements(elements, a) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:523: in _annotate_elements annotation = Annotation( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:314: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:340: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/fbc.py:145: in create_sbml self._set_fields(gene_product, model=model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:314: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:340: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:314: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:340: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:314: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:340: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:314: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:340: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/metadata/annotator.py:257: in annotate_sbml doc = annotate_sbml_doc(doc, external_annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:276: in annotate_sbml_doc annotator.annotate_model() ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:429: in annotate_model self._annotate_elements(elements, a) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:523: in _annotate_elements annotation = Annotation( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/metadata/annotator.py:257: in annotate_sbml doc = annotate_sbml_doc(doc, external_annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:276: in annotate_sbml_doc annotator.annotate_model() ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:429: in annotate_model self._annotate_elements(elements, a) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/metadata/annotator.py:523: in _annotate_elements annotation = Annotation( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e5ac8490> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e5ac87c0> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e539d650> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e5358a50> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:298: in __init__ self.resource_normalized, ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:377: in resource_normalized namespace = get_registry().ns_dict.get(self.collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e56b2b70> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e56b17c0> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e5388e50> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e5388830> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1ec265cc0> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e5397dd0> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1f3d87110> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e52f35f0> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e52f1440> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e537ecb0> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e5cf5910> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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 0x7fa1e45c03d0> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:298: in __init__ self.resource_normalized, ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:377: in resource_normalized namespace = get_registry().ns_dict.get(self.collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: ConnectionError The above exception was the direct cause of the following exception: caplog = <_pytest.logging.LogCaptureFixture object at 0x7fa1de5eb4d0> 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.14/site-packages/pymetadata/core/annotation.py:302: in __init__ self.validate() /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:474: in validate valid_term = self.check_miriam_term() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:413: in check_miriam_term namespace: Namespace | None = get_registry().ns_dict.get( ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:298: in __init__ self.resource_normalized, ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:377: in resource_normalized namespace = get_registry().ns_dict.get(self.collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:797: in create_sbml self._set_fields(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/core_elements.py:1440: in create_sbml _SpeciesReference(modifier)._set_fields(r.createModifier(), model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:1256: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/core_elements.py:1434: in create_sbml _SpeciesReference(reactant)._set_fields(r.createReactant(), model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:1256: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:797: in create_sbml self._set_fields(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7fa1e439f5e0> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7fa1e439f5e0> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7fa1e439f5e0> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/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 0x7fa1e439f5e0> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/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 0x7fa1e439f5e0> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:411: in create_sbml self._set_fields(s, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:417: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/resources/distrib/uncertainty.xml') constructs = ('distrib.package', 'distrib.uncertainty', 'distrib.uncertParameter') package_roundtrip = .compare at 0x7fa1e439f5e0> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1137: in _set_fields self.create_uncertainties(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1404: in create_uncertainties uncertainty.create_sbml(obj, model) for uncertainty in self.uncertainties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/distrib.py:797: in create_sbml self._set_fields(uncertainty, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/resources/distrib/e_coli_core_expression.xml') constructs = ('distrib.package', 'distrib.uncertainty', 'distrib.uncertParameter') package_roundtrip = .compare at 0x7fa1e439f5e0> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/resources/examples/model.xml') constructs = ('distrib.package', 'distrib.uncertainty', 'distrib.uncertParameter') package_roundtrip = .compare at 0x7fa1e439f5e0> @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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7fa1e439f5e0> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7fa1e439f5e0> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7fa1e439f5e0> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7fa1e439f5e0> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: ConnectionError The above exception was the direct cause of the following exception: package_roundtrip = .compare at 0x7fa1e439f5e0> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1141: in _set_fields self.create_key_value_pairs(sbase, model) ../BUILDROOT/usr/lib/python3.14/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.14/site-packages/sbmlutils/factory/_core.py:1605: in create_pairs return [pair.create_sbml(sbase, model) for pair in pairs] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1633: in create_sbml self._set_fields(kvp, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:806: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:924: in _fill_sbml self._create_lists( ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:969: in _create_lists create_objects(model, obj_iter=objects, key=attr) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:118: in create_objects sbml_obj: libsbml.SBase | None = _create_object(obj, model) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:88: in _create_object return obj.create_sbml(container) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:143: in create_sbml self._set_fields(obj, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/core_elements.py:169: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/units.py:614: in _set_fields super()._set_fields(sbase, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1141: in _set_fields self.create_key_value_pairs(sbase, model) ../BUILDROOT/usr/lib/python3.14/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.14/site-packages/sbmlutils/factory/_core.py:1605: in create_pairs return [pair.create_sbml(sbase, model) for pair in pairs] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1633: in create_sbml self._set_fields(kvp, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: ConnectionError The above exception was the direct cause of the following exception: damage = .damage at 0x7fa1e5447320> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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.14/site-packages/urllib3/connection.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/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.14/socket.py:989: 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.33.1', '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 = {}, destination_scheme = None, conn = None release_this_conn = True, http_tunnel_required = False, err = None clean_exit = False 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.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/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.14/site-packages/urllib3/connection.py:246: NameResolutionError The above exception was the direct cause of the following exception: self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:886: in urlopen return self.urlopen( /usr/lib/python3.14/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.14/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.14/site-packages/pymetadata/webservices/webservice.py:136: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:605: in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:592: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:706: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/webservice.py:64: in send return super().send( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=30, read=30, total=None), verify = True, cert = None proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """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 """ 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 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): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=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.14/site-packages/requests/adapters.py:678: ConnectionError The above exception was the direct cause of the following exception: damage = .damage at 0x7fa1e5447480> 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.14/site-packages/sbmlutils/factory/model.py:1769: in create_model ).create_sbml() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1551: in create_sbml return self._create_sbml() ^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:1615: in _create_sbml sbml_model: libsbml.Model = self.model.create_sbml(self.doc) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:805: in create_sbml return self._create_sbml(doc) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:818: in _create_sbml self._fill_sbml(model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/model.py:862: in _fill_sbml self._set_fields(model, model) ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1131: in _set_fields processed_annotations = Sbase._process_annotations(self.annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/sbmlutils/factory/_core.py:1039: in _process_annotations annotations.append(Annotation.from_tuple(annotation_obj)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:342: in from_tuple return RDFAnnotation(qualifier=qualifier, resource=resource) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:290: in __init__ self.term = self.shorten_compact_term( /usr/lib/python3.14/site-packages/pymetadata/core/annotation.py:320: in shorten_compact_term namespace = get_registry().ns_dict.get(collection, None) ^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:306: in get_registry _REGISTRY = Registry() ^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:189: in __init__ self.ns_dict = self.update() ^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/pymetadata/webservices/registry.py:214: in update return Registry.update_registry(registry_path=self.registry_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/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.14/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 421.95s (0:07:01) error: Bad exit status from /var/tmp/rpm-tmp.CvMNUK (%check) Bad exit status from /var/tmp/rpm-tmp.CvMNUK (%check) RPM build errors: Finish: rpmbuild python-sbmlutils-0.17.0-1.fc44.src.rpm Finish: build phase for python-sbmlutils-0.17.0-1.fc44.src.rpm INFO: chroot_scan: 1 files copied to /var/lib/copr-rpmbuild/results/chroot_scan INFO: /var/lib/mock/fedora-44-x86_64-1792824740.810656/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.fc44.src.rpm) Config(fedora-44-x86_64) 7 minutes 27 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 590f746190ad4870a64a81fdef7a5347 -D /var/lib/mock/fedora-44-x86_64-1792824740.810656/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