From b5d8b87f08075944ff87b118922bfb79764d5ef8 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Mon, 20 Oct 2025 13:42:40 +0200 Subject: [PATCH 1/8] ci: Run tests on Python 3.14t --- .github/workflows/test-integrations-common.yml | 2 +- scripts/populate_tox/tox.jinja | 2 +- scripts/split_tox_gh_actions/split_tox_gh_actions.py | 12 ++++++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-integrations-common.yml b/.github/workflows/test-integrations-common.yml index eb5dde8b17..9efe696fe5 100644 --- a/.github/workflows/test-integrations-common.yml +++ b/.github/workflows/test-integrations-common.yml @@ -29,7 +29,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13"] + python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13","3.14t"] # python3.6 reached EOL and is no longer being supported on # new versions of hosted runners on Github Actions # ubuntu-20.04 is the last version that supported python3.6 diff --git a/scripts/populate_tox/tox.jinja b/scripts/populate_tox/tox.jinja index b86da57c24..9a25e88117 100755 --- a/scripts/populate_tox/tox.jinja +++ b/scripts/populate_tox/tox.jinja @@ -18,7 +18,7 @@ requires = virtualenv<20.26.3 envlist = # === Common === - {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-common + {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12,py3.13,py3.14t}-common # === Gevent === {py3.6,py3.8,py3.10,py3.11,py3.12}-gevent diff --git a/scripts/split_tox_gh_actions/split_tox_gh_actions.py b/scripts/split_tox_gh_actions/split_tox_gh_actions.py index 9dea95842b..12222eff1b 100755 --- a/scripts/split_tox_gh_actions/split_tox_gh_actions.py +++ b/scripts/split_tox_gh_actions/split_tox_gh_actions.py @@ -28,7 +28,7 @@ TOXENV_REGEX = re.compile( r""" - {?(?P(py\d+\.\d+,?)+)}? + {?(?P(py\d+\.\d+t?,?)+)}? -(?P[a-z](?:[a-z_]|-(?!v{?\d))*[a-z0-9]) (?:-( (v{?(?P[0-9.]+[0-9a-z,.]*}?)) @@ -250,11 +250,19 @@ def find_frameworks_missing_from_groups(py_versions): return all_frameworks - frameworks_in_a_group +def _version_key(v): + major_version, minor_version_and_suffix = v.split(".") + if minor_version_and_suffix.endswith("t"): + return int(major_version), int(minor_version_and_suffix.rstrip("t")), 1 + + return int(major_version), int(minor_version_and_suffix), 0 + + def _normalize_py_versions(py_versions): def replace_and_sort(versions): return sorted( [py.replace("py", "") for py in versions], - key=lambda v: tuple(map(int, v.split("."))), + key=_version_key, ) if isinstance(py_versions, dict): From de3cecf8bd343b7ac50b16fa6fc8d94eff243c6d Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Tue, 21 Oct 2025 14:07:49 +0200 Subject: [PATCH 2/8] fix tox --- tox.ini | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tox.ini b/tox.ini index ae3d7db813..bb9a65dc1a 100644 --- a/tox.ini +++ b/tox.ini @@ -57,8 +57,9 @@ envlist = {py3.9,py3.11,py3.12}-cohere-v5.15.0 {py3.9,py3.11,py3.12}-cohere-v5.19.0 - {py3.9,py3.11,py3.12}-google_genai-v0.0.1 - {py3.9,py3.12,py3.13}-google_genai-v0.8.0 + {py3.9,py3.12,py3.13}-google_genai-v1.29.0 + {py3.9,py3.12,py3.13}-google_genai-v1.34.0 + {py3.9,py3.12,py3.13}-google_genai-v1.39.1 {py3.9,py3.12,py3.13}-google_genai-v1.45.0 {py3.8,py3.10,py3.11}-huggingface_hub-v0.24.7 @@ -354,8 +355,9 @@ deps = cohere-v5.15.0: cohere==5.15.0 cohere-v5.19.0: cohere==5.19.0 - google_genai-v0.0.1: google-genai==0.0.1 - google_genai-v0.8.0: google-genai==0.8.0 + google_genai-v1.29.0: google-genai==1.29.0 + google_genai-v1.34.0: google-genai==1.34.0 + google_genai-v1.39.1: google-genai==1.39.1 google_genai-v1.45.0: google-genai==1.45.0 google_genai: pytest-asyncio From 98a1cf01ae9c43c89a52dd1aa538f54d135c7067 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Tue, 21 Oct 2025 15:20:12 +0200 Subject: [PATCH 3/8] pin jsonschema --- requirements-testing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-testing.txt b/requirements-testing.txt index 5cd669af9a..0ab909d201 100644 --- a/requirements-testing.txt +++ b/requirements-testing.txt @@ -5,7 +5,7 @@ pytest-cov pytest-forked pytest-localserver pytest-watch -jsonschema +jsonschema<4.18 executing asttokens responses From 2048ee035b65dafe1b2b93cf25a36f3c35fe5e24 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Tue, 21 Oct 2025 16:06:27 +0200 Subject: [PATCH 4/8] remove version constraint --- requirements-testing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-testing.txt b/requirements-testing.txt index 0ab909d201..5cd669af9a 100644 --- a/requirements-testing.txt +++ b/requirements-testing.txt @@ -5,7 +5,7 @@ pytest-cov pytest-forked pytest-localserver pytest-watch -jsonschema<4.18 +jsonschema executing asttokens responses From 148b81f7091b472ab9f89bba40a0eaf7b1b9afc1 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 22 Oct 2025 08:57:02 +0200 Subject: [PATCH 5/8] use higher pip --- scripts/populate_tox/tox.jinja | 3 +++ tox.ini | 41 +++++++++++++++++----------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/scripts/populate_tox/tox.jinja b/scripts/populate_tox/tox.jinja index 926c2b0c94..4de4d94b5f 100755 --- a/scripts/populate_tox/tox.jinja +++ b/scripts/populate_tox/tox.jinja @@ -134,6 +134,9 @@ setenv = OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES COVERAGE_FILE=.coverage-sentry-{envname} py3.6: COVERAGE_RCFILE=.coveragerc36 + # Lowest version to support free-threading + # https://discuss.python.org/t/announcement-pip-24-1-release/56281 + py3.14t: VIRTUALENV_PIP=24.1 django: DJANGO_SETTINGS_MODULE=tests.integrations.django.myapp.settings spark-v{3.0.3,3.5.6}: JAVA_HOME=/usr/lib/jvm/temurin-11-jdk-amd64 diff --git a/tox.ini b/tox.ini index bb9a65dc1a..27282ac534 100644 --- a/tox.ini +++ b/tox.ini @@ -58,15 +58,15 @@ envlist = {py3.9,py3.11,py3.12}-cohere-v5.19.0 {py3.9,py3.12,py3.13}-google_genai-v1.29.0 - {py3.9,py3.12,py3.13}-google_genai-v1.34.0 - {py3.9,py3.12,py3.13}-google_genai-v1.39.1 - {py3.9,py3.12,py3.13}-google_genai-v1.45.0 + {py3.9,py3.12,py3.13}-google_genai-v1.35.0 + {py3.9,py3.12,py3.13}-google_genai-v1.41.0 + {py3.9,py3.12,py3.13}-google_genai-v1.46.0 {py3.8,py3.10,py3.11}-huggingface_hub-v0.24.7 {py3.8,py3.12,py3.13}-huggingface_hub-v0.28.1 {py3.8,py3.12,py3.13}-huggingface_hub-v0.32.6 {py3.8,py3.12,py3.13}-huggingface_hub-v0.35.3 - {py3.9,py3.12,py3.13}-huggingface_hub-v1.0.0rc6 + {py3.9,py3.12,py3.13}-huggingface_hub-v1.0.0rc7 {py3.9,py3.11,py3.12}-langchain-base-v0.1.20 {py3.9,py3.11,py3.12}-langchain-base-v0.2.17 @@ -80,7 +80,7 @@ envlist = {py3.10,py3.12,py3.13}-langgraph-v1.0.1 {py3.9,py3.12,py3.13}-litellm-v1.77.7 - {py3.9,py3.12,py3.13}-litellm-v1.78.5 + {py3.9,py3.12,py3.13}-litellm-v1.78.6 {py3.8,py3.11,py3.12}-openai-base-v1.0.1 {py3.8,py3.12,py3.13}-openai-base-v1.109.1 @@ -93,14 +93,14 @@ envlist = {py3.10,py3.11,py3.12}-openai_agents-v0.0.19 {py3.10,py3.12,py3.13}-openai_agents-v0.1.0 {py3.10,py3.12,py3.13}-openai_agents-v0.2.11 - {py3.10,py3.12,py3.13}-openai_agents-v0.4.0 + {py3.10,py3.12,py3.13}-openai_agents-v0.4.1 # ~~~ Cloud ~~~ {py3.6,py3.7}-boto3-v1.12.49 {py3.6,py3.9,py3.10}-boto3-v1.20.54 {py3.7,py3.11,py3.12}-boto3-v1.28.85 - {py3.9,py3.12,py3.13}-boto3-v1.40.55 + {py3.9,py3.12,py3.13}-boto3-v1.40.56 {py3.6,py3.7,py3.8}-chalice-v1.16.0 {py3.9,py3.12,py3.13}-chalice-v1.32.0 @@ -166,8 +166,7 @@ envlist = {py3.7,py3.8}-grpc-v1.32.0 {py3.7,py3.9,py3.10}-grpc-v1.47.5 {py3.7,py3.11,py3.12}-grpc-v1.62.3 - {py3.9,py3.12,py3.13}-grpc-v1.75.1 - {py3.9,py3.12,py3.13}-grpc-v1.76.0rc1 + {py3.9,py3.12,py3.13}-grpc-v1.76.0 {py3.6,py3.8,py3.9}-httpx-v0.16.1 {py3.6,py3.9,py3.10}-httpx-v0.20.0 @@ -184,7 +183,7 @@ envlist = {py3.7}-beam-v2.14.0 {py3.9,py3.12,py3.13}-beam-v2.68.0 - {py3.9,py3.12,py3.13}-beam-v2.69.0rc1 + {py3.9,py3.12,py3.13}-beam-v2.69.0rc3 {py3.6,py3.7,py3.8}-celery-v4.4.7 {py3.8,py3.12,py3.13}-celery-v5.5.3 @@ -356,16 +355,16 @@ deps = cohere-v5.19.0: cohere==5.19.0 google_genai-v1.29.0: google-genai==1.29.0 - google_genai-v1.34.0: google-genai==1.34.0 - google_genai-v1.39.1: google-genai==1.39.1 - google_genai-v1.45.0: google-genai==1.45.0 + google_genai-v1.35.0: google-genai==1.35.0 + google_genai-v1.41.0: google-genai==1.41.0 + google_genai-v1.46.0: google-genai==1.46.0 google_genai: pytest-asyncio huggingface_hub-v0.24.7: huggingface_hub==0.24.7 huggingface_hub-v0.28.1: huggingface_hub==0.28.1 huggingface_hub-v0.32.6: huggingface_hub==0.32.6 huggingface_hub-v0.35.3: huggingface_hub==0.35.3 - huggingface_hub-v1.0.0rc6: huggingface_hub==1.0.0rc6 + huggingface_hub-v1.0.0rc7: huggingface_hub==1.0.0rc7 huggingface_hub: responses huggingface_hub: pytest-httpx @@ -388,7 +387,7 @@ deps = langgraph-v1.0.1: langgraph==1.0.1 litellm-v1.77.7: litellm==1.77.7 - litellm-v1.78.5: litellm==1.78.5 + litellm-v1.78.6: litellm==1.78.6 openai-base-v1.0.1: openai==1.0.1 openai-base-v1.109.1: openai==1.109.1 @@ -406,7 +405,7 @@ deps = openai_agents-v0.0.19: openai-agents==0.0.19 openai_agents-v0.1.0: openai-agents==0.1.0 openai_agents-v0.2.11: openai-agents==0.2.11 - openai_agents-v0.4.0: openai-agents==0.4.0 + openai_agents-v0.4.1: openai-agents==0.4.1 openai_agents: pytest-asyncio @@ -414,7 +413,7 @@ deps = boto3-v1.12.49: boto3==1.12.49 boto3-v1.20.54: boto3==1.20.54 boto3-v1.28.85: boto3==1.28.85 - boto3-v1.40.55: boto3==1.40.55 + boto3-v1.40.56: boto3==1.40.56 {py3.7,py3.8}-boto3: urllib3<2.0.0 chalice-v1.16.0: chalice==1.16.0 @@ -500,8 +499,7 @@ deps = grpc-v1.32.0: grpcio==1.32.0 grpc-v1.47.5: grpcio==1.47.5 grpc-v1.62.3: grpcio==1.62.3 - grpc-v1.75.1: grpcio==1.75.1 - grpc-v1.76.0rc1: grpcio==1.76.0rc1 + grpc-v1.76.0: grpcio==1.76.0 grpc: protobuf grpc: mypy-protobuf grpc: types-protobuf @@ -531,7 +529,7 @@ deps = beam-v2.14.0: apache-beam==2.14.0 beam-v2.68.0: apache-beam==2.68.0 - beam-v2.69.0rc1: apache-beam==2.69.0rc1 + beam-v2.69.0rc3: apache-beam==2.69.0rc3 beam: dill celery-v4.4.7: celery==4.4.7 @@ -730,6 +728,9 @@ setenv = OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES COVERAGE_FILE=.coverage-sentry-{envname} py3.6: COVERAGE_RCFILE=.coveragerc36 + # Lowest version to support free-threading + # https://discuss.python.org/t/announcement-pip-24-1-release/56281 + py3.14t: VIRTUALENV_PIP=24.1 django: DJANGO_SETTINGS_MODULE=tests.integrations.django.myapp.settings spark-v{3.0.3,3.5.6}: JAVA_HOME=/usr/lib/jvm/temurin-11-jdk-amd64 From 7c33ac3625ad86987a7a33f4f0d319f9119140f2 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 22 Oct 2025 13:23:51 +0200 Subject: [PATCH 6/8] check thread_inherit_context --- tests/integrations/threading/test_threading.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/integrations/threading/test_threading.py b/tests/integrations/threading/test_threading.py index 9c9a24aa63..11a21727b0 100644 --- a/tests/integrations/threading/test_threading.py +++ b/tests/integrations/threading/test_threading.py @@ -1,4 +1,5 @@ import gc +import sys from concurrent import futures from textwrap import dedent from threading import Thread @@ -68,7 +69,9 @@ def stage2(): assert exception["mechanism"]["type"] == "threading" assert not exception["mechanism"]["handled"] - if propagate_hub: + # Free-threaded builds set thread_inherit_context to True, otherwise thread_inherit_context is False + # https://docs.python.org/3/howto/free-threading-python.html + if propagate_hub or sys.flags.thread_inherit_context: assert event["tags"]["stage1"] == "true" else: assert "stage1" not in event.get("tags", {}) @@ -94,7 +97,9 @@ def double(number): sentry_sdk.flush() - if propagate_hub: + # Free-threaded builds set thread_inherit_context to True, otherwise thread_inherit_context is False + # https://docs.python.org/3/howto/free-threading-python.html + if propagate_hub or sys.flags.thread_inherit_context: assert len(events) == 1 (event,) = events assert event["spans"][0]["trace_id"] == event["spans"][1]["trace_id"] @@ -248,7 +253,10 @@ def do_some_work(number): t.join() (event,) = events - if propagate_scope: + + # Free-threaded builds set thread_inherit_context to True, otherwise thread_inherit_context is False + # https://docs.python.org/3/howto/free-threading-python.html + if propagate_scope or sys.flags.thread_inherit_context: assert render_span_tree(event) == dedent( """\ - op="outer-trx": description=null @@ -309,7 +317,9 @@ def do_some_work(number): (event,) = events - if propagate_scope: + # Free-threaded builds set thread_inherit_context to True, otherwise thread_inherit_context is False + # https://docs.python.org/3/howto/free-threading-python.html + if propagate_scope or sys.flags.thread_inherit_context: assert render_span_tree(event) == dedent( """\ - op="outer-trx": description=null From cf7f843d5b1d07e6eb5093a525df89fc7c06ddc9 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 22 Oct 2025 13:33:54 +0200 Subject: [PATCH 7/8] check if flag exists --- tests/integrations/threading/test_threading.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/integrations/threading/test_threading.py b/tests/integrations/threading/test_threading.py index 11a21727b0..788fb24fdf 100644 --- a/tests/integrations/threading/test_threading.py +++ b/tests/integrations/threading/test_threading.py @@ -70,8 +70,7 @@ def stage2(): assert not exception["mechanism"]["handled"] # Free-threaded builds set thread_inherit_context to True, otherwise thread_inherit_context is False - # https://docs.python.org/3/howto/free-threading-python.html - if propagate_hub or sys.flags.thread_inherit_context: + if propagate_hub or getattr(sys.flags, "thread_inherit_context", None): assert event["tags"]["stage1"] == "true" else: assert "stage1" not in event.get("tags", {}) @@ -98,8 +97,7 @@ def double(number): sentry_sdk.flush() # Free-threaded builds set thread_inherit_context to True, otherwise thread_inherit_context is False - # https://docs.python.org/3/howto/free-threading-python.html - if propagate_hub or sys.flags.thread_inherit_context: + if propagate_hub or getattr(sys.flags, "thread_inherit_context", None): assert len(events) == 1 (event,) = events assert event["spans"][0]["trace_id"] == event["spans"][1]["trace_id"] @@ -255,8 +253,7 @@ def do_some_work(number): (event,) = events # Free-threaded builds set thread_inherit_context to True, otherwise thread_inherit_context is False - # https://docs.python.org/3/howto/free-threading-python.html - if propagate_scope or sys.flags.thread_inherit_context: + if propagate_scope or getattr(sys.flags, "thread_inherit_context", None): assert render_span_tree(event) == dedent( """\ - op="outer-trx": description=null @@ -318,8 +315,7 @@ def do_some_work(number): (event,) = events # Free-threaded builds set thread_inherit_context to True, otherwise thread_inherit_context is False - # https://docs.python.org/3/howto/free-threading-python.html - if propagate_scope or sys.flags.thread_inherit_context: + if propagate_scope or getattr(sys.flags, "thread_inherit_context", None): assert render_span_tree(event) == dedent( """\ - op="outer-trx": description=null From 2bfc6bc76fc0037b593cc7b4413e032d542ba4a4 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 22 Oct 2025 15:25:02 +0200 Subject: [PATCH 8/8] regenerate tox --- tox.ini | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tox.ini b/tox.ini index 27282ac534..ef7b0e85b9 100644 --- a/tox.ini +++ b/tox.ini @@ -60,7 +60,7 @@ envlist = {py3.9,py3.12,py3.13}-google_genai-v1.29.0 {py3.9,py3.12,py3.13}-google_genai-v1.35.0 {py3.9,py3.12,py3.13}-google_genai-v1.41.0 - {py3.9,py3.12,py3.13}-google_genai-v1.46.0 + {py3.9,py3.13,py3.14}-google_genai-v1.46.0 {py3.8,py3.10,py3.11}-huggingface_hub-v0.24.7 {py3.8,py3.12,py3.13}-huggingface_hub-v0.28.1 @@ -76,7 +76,7 @@ envlist = {py3.9,py3.11,py3.12}-langchain-notiktoken-v0.2.17 {py3.9,py3.12,py3.13}-langchain-notiktoken-v0.3.27 - {py3.9,py3.12,py3.13}-langgraph-v0.6.11 + {py3.9,py3.13,py3.14}-langgraph-v0.6.11 {py3.10,py3.12,py3.13}-langgraph-v1.0.1 {py3.9,py3.12,py3.13}-litellm-v1.77.7 @@ -100,7 +100,7 @@ envlist = {py3.6,py3.7}-boto3-v1.12.49 {py3.6,py3.9,py3.10}-boto3-v1.20.54 {py3.7,py3.11,py3.12}-boto3-v1.28.85 - {py3.9,py3.12,py3.13}-boto3-v1.40.56 + {py3.9,py3.13,py3.14}-boto3-v1.40.56 {py3.6,py3.7,py3.8}-chalice-v1.16.0 {py3.9,py3.12,py3.13}-chalice-v1.32.0 @@ -135,13 +135,13 @@ envlist = # ~~~ Flags ~~~ {py3.8,py3.12,py3.13}-launchdarkly-v9.8.1 - {py3.9,py3.12,py3.13}-launchdarkly-v9.12.1 + {py3.9,py3.13,py3.14}-launchdarkly-v9.12.1 - {py3.8,py3.12,py3.13}-openfeature-v0.7.5 - {py3.9,py3.12,py3.13}-openfeature-v0.8.3 + {py3.8,py3.13,py3.14}-openfeature-v0.7.5 + {py3.9,py3.13,py3.14}-openfeature-v0.8.3 - {py3.7,py3.12,py3.13}-statsig-v0.55.3 - {py3.7,py3.12,py3.13}-statsig-v0.66.0 + {py3.7,py3.13,py3.14}-statsig-v0.55.3 + {py3.7,py3.13,py3.14}-statsig-v0.66.0 {py3.8,py3.12,py3.13}-unleash-v6.0.1 {py3.8,py3.12,py3.13}-unleash-v6.3.0 @@ -159,14 +159,14 @@ envlist = {py3.8,py3.12,py3.13}-graphene-v3.4.3 {py3.8,py3.10,py3.11}-strawberry-v0.209.8 - {py3.10,py3.12,py3.13}-strawberry-v0.284.1 + {py3.10,py3.13,py3.14}-strawberry-v0.284.1 # ~~~ Network ~~~ {py3.7,py3.8}-grpc-v1.32.0 {py3.7,py3.9,py3.10}-grpc-v1.47.5 {py3.7,py3.11,py3.12}-grpc-v1.62.3 - {py3.9,py3.12,py3.13}-grpc-v1.76.0 + {py3.9,py3.13,py3.14}-grpc-v1.76.0 {py3.6,py3.8,py3.9}-httpx-v0.16.1 {py3.6,py3.9,py3.10}-httpx-v0.20.0 @@ -174,7 +174,7 @@ envlist = {py3.9,py3.11,py3.12}-httpx-v0.28.1 {py3.6}-requests-v2.12.5 - {py3.9,py3.12,py3.13}-requests-v2.32.5 + {py3.9,py3.13,py3.14}-requests-v2.32.5 # ~~~ Tasks ~~~ @@ -217,25 +217,25 @@ envlist = {py3.12,py3.13}-django-v6.0a1 {py3.6,py3.7,py3.8}-flask-v1.1.4 - {py3.8,py3.12,py3.13}-flask-v2.3.3 - {py3.9,py3.12,py3.13}-flask-v3.1.2 + {py3.8,py3.13,py3.14}-flask-v2.3.3 + {py3.9,py3.13,py3.14}-flask-v3.1.2 {py3.6,py3.9,py3.10}-starlette-v0.16.0 {py3.7,py3.10,py3.11}-starlette-v0.27.0 {py3.8,py3.12,py3.13}-starlette-v0.38.6 - {py3.9,py3.12,py3.13}-starlette-v0.48.0 + {py3.9,py3.13,py3.14}-starlette-v0.48.0 {py3.6,py3.9,py3.10}-fastapi-v0.79.1 {py3.7,py3.10,py3.11}-fastapi-v0.92.0 {py3.8,py3.10,py3.11}-fastapi-v0.105.0 - {py3.8,py3.12,py3.13}-fastapi-v0.119.1 + {py3.8,py3.13,py3.14}-fastapi-v0.119.1 # ~~~ Web 2 ~~~ {py3.7}-aiohttp-v3.4.4 {py3.7,py3.8,py3.9}-aiohttp-v3.7.4 {py3.8,py3.12,py3.13}-aiohttp-v3.10.11 - {py3.9,py3.12,py3.13}-aiohttp-v3.13.1 + {py3.9,py3.13,py3.14}-aiohttp-v3.13.1 {py3.6,py3.7}-bottle-v0.12.25 {py3.8,py3.12,py3.13}-bottle-v0.13.4 @@ -255,7 +255,7 @@ envlist = {py3.6,py3.10,py3.11}-pyramid-v2.0.2 {py3.7,py3.9,py3.10}-quart-v0.16.3 - {py3.9,py3.12,py3.13}-quart-v0.20.0 + {py3.9,py3.13,py3.14}-quart-v0.20.0 {py3.6}-sanic-v0.8.3 {py3.6,py3.8,py3.9}-sanic-v20.12.7 @@ -282,7 +282,7 @@ envlist = {py3.9,py3.12,py3.13}-trytond-v7.6.9 {py3.7,py3.12,py3.13}-typer-v0.15.4 - {py3.8,py3.12,py3.13}-typer-v0.20.0 + {py3.8,py3.13,py3.14}-typer-v0.20.0