Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,24 @@ jobs:
# GIL disabled; see docs/free-threading.md.
- "3.14t"
experimental: [ false ]
include:
# Python 3.15, which `allow-prereleases` below resolves to the
# newest pre-release the runner image publishes -- 3.15.0rc1 at the
# time of writing, and 3.15.0 itself once it ships in October 2026,
# with no change needed here.
#
# Advisory (`experimental: true` -> `continue-on-error`) while 3.15
# is a pre-release: the suite passes on 3.15.0rc1 today, but rc2 and
# the final release are still to come, and a regression in CPython
# itself -- or a test dependency that has no 3.15 wheels yet and
# fails to build from source -- must not block merges on a version
# nothing runs in production. Move these two entries up into the
# `python-version` list above (and delete them from `include`) to
# make 3.15 a required check once 3.15.0 final is out.
- python-version: "3.15"
experimental: true
- python-version: "3.15t"
experimental: true

steps:
- uses: actions/checkout@v4
Expand All @@ -49,6 +67,13 @@ jobs:
- uses: "actions/setup-python@v5"
with:
python-version: "${{ matrix.python-version }}"
# Required for the 3.15 rows: without it the version spec only
# matches stable releases and the job fails with "Version 3.15 was
# not found in the local cache". It is safe to set for every row --
# it widens `3.X` to `~3.X.0-0`, and a pre-release only wins when no
# stable release satisfies the spec, so 3.10-3.14 still resolve to
# their newest stable patch.
allow-prereleases: true
cache: "pip"
cache-dependency-path: |
requirements-docs.txt
Expand Down
39 changes: 35 additions & 4 deletions mode/utils/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from contextlib import suppress
from decimal import Decimal
from functools import total_ordering
from inspect import get_annotations
from inspect import get_annotations, signature
from pathlib import Path
from typing import (
Any,
Expand All @@ -34,11 +34,42 @@
)

try:
from typing import _eval_type # type: ignore
except ImportError:
from typing import _eval_type as _typing_eval_type # type: ignore
except ImportError: # pragma: no cover
_typing_eval_type = None
_EVAL_TYPE_WANTS_TYPE_PARAMS = False
else:
# `type_params` (the PEP 695 type parameters in scope) was added to
# `typing._eval_type` in 3.13, where omitting it only emitted a
# DeprecationWarning and defaulted to `()`. On 3.15 it became a required
# positional argument, so calling without it now fails outright with
# "TypeError: _eval_type() missing 1 required positional argument:
# 'type_params'".
#
# The signature is inspected once, here at import. A try/except TypeError
# around the call would be wrong: `_eval_type` legitimately raises
# TypeError for annotations `typing._type_check` rejects, and `eval_type`
# below depends on being able to tell those apart.
_EVAL_TYPE_WANTS_TYPE_PARAMS = (
"type_params" in signature(_typing_eval_type).parameters
)


def _eval_type(t, globalns, localns, recursive_guard=frozenset()): # type: ignore
def _eval_type(
t: Any,
globalns: Optional[dict[str, Any]],
localns: Optional[dict[str, Any]],
) -> Any:
# Nothing resolved through here carries PEP 695 type parameters of its
# own, so `()` is both what 3.13/3.14 already substituted when the
# argument was omitted and what 3.15 requires -- passing it explicitly
# keeps behaviour identical across versions, and silences the 3.13/3.14
# deprecation warning on the way.
if _typing_eval_type is None: # pragma: no cover
return t
if _EVAL_TYPE_WANTS_TYPE_PARAMS:
return _typing_eval_type(t, globalns, localns, ())
return _typing_eval_type(t, globalns, localns)


def _is_class_var(typ: Any) -> bool:
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ classifiers = [
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.15",
"Programming Language :: Python :: Free Threading :: 2 - Beta",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
Expand Down
Loading