Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e3a5fa9
chore: update Python interpreter constraints to 3.14.1
achimnol Dec 8, 2025
4d6deb2
chore: upgrade dependencies for Python 3.14 compatibility
achimnol Dec 8, 2025
4e9f94a
doc: Update README
achimnol Dec 9, 2025
c36e9fc
chore: Update tool lockfiles
achimnol Dec 10, 2025
c130046
chore: Update pex/pip versions
achimnol Dec 10, 2025
5b9952d
deps: Upgrade Python dependencies for 3.14 support
achimnol Dec 10, 2025
39f77fa
Merge branch 'main' into chore/python-3.14-upgrade
achimnol Dec 10, 2025
978c5ec
Merge branch 'main' into chore/python-3.14-upgrade
achimnol Dec 10, 2025
b19915b
deps: Update main dependency sets and lockfiles
achimnol Dec 10, 2025
8aa7fe2
deps: Sync pydantic version of the mypy tool resolve and the main req…
achimnol Dec 10, 2025
01a64a7
deps: Change target Python version to 3.14.2
achimnol Dec 10, 2025
fff19b5
doc: Update mentions in docs
achimnol Dec 10, 2025
2e713c5
chore: Upgrade mypy to 1.19
achimnol Dec 10, 2025
3cb49bd
fix: Type errors
achimnol Dec 10, 2025
1fe245f
chore: Update ruff version (0.14.0 -> 0.14.8)
achimnol Dec 10, 2025
9541470
chore: Update Python versions in pyscript.sh, python.sh and build-mac…
achimnol Dec 10, 2025
9c42f91
chore: Ensure Python 3.13 syntax compatibility when formatting/linting
achimnol Dec 10, 2025
e8e1487
Merge branch 'main' into chore/python-3.14-upgrade
achimnol Dec 11, 2025
9b8150e
Merge branch 'main' into chore/python-3.14-upgrade
achimnol Jan 8, 2026
bfb0d40
Merge branch 'main' into chore/python-3.14-upgrade
achimnol Jan 8, 2026
074659f
Merge branch 'main' into chore/python-3.14-upgrade
achimnol Jan 8, 2026
a74b78b
chore: Regenerate black lockfile (resolving merge conflict)
achimnol Jan 8, 2026
30d3760
fix: Type error induced by aiohttp 3.13.3's breaking public API change
achimnol Jan 8, 2026
efd445d
Merge branch 'main' into chore/python-3.14-upgrade
achimnol Jan 8, 2026
efa9608
Merge branch 'main' into chore/python-3.14-upgrade
achimnol Jan 9, 2026
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ Requirements

### Python & Build Tools

- **Python**: 3.13.x (main branch requires CPython 3.13.7)
- **Pantsbuild**: 2.27.x
- **Python**: 3.14.x (main branch requires CPython 3.14.2)
- **Pantsbuild**: 2.29.x
- See [full version compatibility table](src/ai/backend/README.md#development-setup)

### Infrastructure
Expand Down
6 changes: 3 additions & 3 deletions docs/install/install-from-package/os-preparation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@ For example,

.. code-block:: console

$ curl -L "https://github.com/astral-sh/python-build-standalone/releases/download/20241219/cpython-3.13.3+20250409-x86_64-unknown-linux-gnu-install_only.tar.gz" > cpython-3.13.3+20250409-x86_64-unknown-linux-gnu-install_only.tar.gz
$ tar -xf "cpython-3.13.3+20241219-x86_64-unknown-linux-gnu-install_only.tar.gz"
$ curl -L "https://github.com/astral-sh/python-build-standalone/releases/download/20251209/cpython-3.14.2+20251209-x86_64-unknown-linux-gnu-install_only.tar.gz" > cpython-3.14.2+20251209-x86_64-unknown-linux-gnu-install_only.tar.gz
$ tar -xf "cpython-3.14.2+20251209-x86_64-unknown-linux-gnu-install_only.tar.gz"
$ mkdir -p "/home/bai/.static-python/versions"
$ mv python "/home/bai/.static-python/versions/3.13.3"
$ mv python "/home/bai/.static-python/versions/3.14.2"

Then, you can create multiple virtual environments per service. To create a
virtual environment for Backend.AI Manager and activate it, for example, you may run:
Expand Down
13 changes: 7 additions & 6 deletions pants.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ enable_resolves = true
# * Let other developers do:
# - Run `pants export` again
# - Update their local IDE/editor's interpreter path configurations
interpreter_constraints = ["CPython==3.13.7"]
interpreter_constraints = ["CPython==3.14.2"]
interpreter_versions_universe = ["3.11", "3.12", "3.13", "3.14"]
tailor_pex_binary_targets = false
pip_version = "25.3"

Expand Down Expand Up @@ -109,13 +110,13 @@ known_versions = [
install_from_resolve = "black"

[ruff]
version = "0.14.0"
version = "0.14.8"
# take tar.gz files and their checksums from the GitHub release (darwin and linux-musl)
known_versions = [
"0.14.0|macos_arm64|0b7c193d5c45eda02226720eb75239fabeca995d5a0eb3830fd2973caa3030ec|12364514",
"0.14.0|macos_x86_64|880ae046b435eb306cd557a7481eed6da463b85f283ba1f2c1e2ad7c139ed6c5|13149751",
"0.14.0|linux_arm64|34a25398f03e7d32a4ec406c5c841c6e183fa0a96fbdd40b7e7eec1f177b360e|12465179",
"0.14.0|linux_x86_64|ed6d1b8407a1d228dc332fb19057e86e04a6cd3c2beacdb324ad6ff2a3f9071b|13647531",
"0.14.8|macos_arm64|4efc019832a6b9225f650ee256d31b2e875021cae662963d533c78b5cf865f52|12262293",
"0.14.8|macos_x86_64|c53af0ba3cbc5e9e8f7768d28a7ff2d0795843e39302891093227bc6df343e94|13284305",
"0.14.8|linux_arm64|0b3464f54fa56f514c29e92bcf05867b914ad6c246e2ddbe4cce5c0700f2a3d9|12604548",
"0.14.8|linux_x86_64|0f5496a3d2413b3cb85bbf9e4a6f95b5db127ac10989ecb3d8c0c0a0a74a892b|13826546",
]

[pytest]
Expand Down
9 changes: 5 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[project]
requires-python = "~=3.13.7"
requires-python = "~=3.14.2"
name = "backend.ai"
dynamic = ["version"]

Expand Down Expand Up @@ -78,6 +78,7 @@ asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"

[tool.ruff]
target-version = "py313" # keep Python 3.13 compatibility for backports
line-length = 100
src = ["src"]

Expand Down Expand Up @@ -265,11 +266,11 @@ follow_untyped_imports = false
mypy_path = "stubs:src:tools/pants-plugins"
namespace_packages = true
explicit_package_bases = true
python_executable = "dist/export/python/virtualenvs/python-default/3.13.7/bin/python"
python_executable = "dist/export/python/virtualenvs/python-default/3.14.2/bin/python"
disable_error_code = ["typeddict-unknown-key"]

[tool.pyright]
pythonVersion = "3.13"
pythonVersion = "3.14"
include = [
"src",
"tools/pants-plugins",
Expand All @@ -282,7 +283,7 @@ exclude = [
"src/ai/backend/web/static",
]
venvPath = "dist/export/python/virtualenvs/python-default"
venv = "3.13.7"
venv = "3.14.2"
typeCheckingMode = "standard"

[tool.pydantic-mypy]
Expand Down
335 changes: 175 additions & 160 deletions python-kernel.lock

Large diffs are not rendered by default.

2,542 changes: 1,521 additions & 1,021 deletions python.lock

Large diffs are not rendered by default.

58 changes: 30 additions & 28 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,52 @@ aiofiles~=24.1.0
aiohttp~=3.13.3
aiohttp_cors~=0.8.1
aiohttp_jinja2~=1.6
aiohttp_sse>=2.2
aiodns==3.2
aiohttp_sse~=2.2
aiodns~=3.2
aiomonitor~=0.7.0
aioresponses>=0.7.3
aioresponses~=0.7.8
aiosqlite~=0.21.0
aiotools~=2.2.3
aiotusclient~=0.1.4
alembic~=1.13.2
appdirs~=1.4.4
async_timeout~=4.0
asyncpg>=0.29.0
asynctest>=0.13.0
asyncudp>=0.11
attrs>=25.3
bcrypt~=4.2.0
asyncpg~=0.31.0
asynctest~=0.13.0
asyncudp~=0.11
attrs~=25.3
bcrypt~=5.0.0
boto3~=1.35
cachetools~=5.5.0
callosum~=1.0.3
cattrs~=24.1.1
click~=8.1.7
coloredlogs~=15.0
colorama>=0.4.6
cryptography>=44.0.2
colorama~=0.4.6
cryptography~=44.0.2
dataclasses-json~=0.5.7
faker~=24.7.1
graphene~=3.3.0
graphene-federation~=3.2.0
graphql-core~=3.2.6
graphql-relay~=3.2.0
graypy==2.1.0
humanize>=3.1.0
humanize~=4.11
ifaddr~=0.2
inquirer~=3.3.0
janus~=2.0
Jinja2~=3.1.6
jupyter-client>=8.6
jupyter-client~=8.6
kubernetes~=33.1.0
kubernetes-asyncio~=33.3.0
lark~=1.1.5
memray~=1.17.2
memray~=1.19.0
more-itertools~=10.5.0
msgpack~=1.1.0
multidict~=6.6.4
msgpack~=1.1.2
multidict~=6.7.0
namedlist~=1.8
networkx~=3.3.0
orjson~=3.10.16
networkx~=3.6.1
orjson~=3.11.0
opentelemetry-api~=1.39.0
opentelemetry-sdk~=1.39.0
opentelemetry-exporter-otlp-proto-grpc~=1.39.0
Expand All @@ -60,31 +60,33 @@ opentelemetry-instrumentation-logging~=0.60b0
pexpect~=4.8
prometheus-client~=0.21.1
psutil~=7.0
pycryptodome~=3.21
pycares~=4.11.0
pycryptodome>=3.20.0
habana-pyhlml~=1.22.1.6
pyhumps~=3.8.0
pyroscope-io~=0.8.8
python-dateutil>=2.9
python-dateutil~=2.9
python-dotenv~=0.20.0
python-json-logger~=3.2.0
pyzmq~=26.4
PyJWT~=2.10.1
PyYAML~=6.0
pydantic[email]~=2.11.3
packaging>=24.1
hiredis>=3.0.0
pydantic[email]~=2.12.0
packaging~=24.2
hiredis~=3.3.0
huggingface-hub~=0.34.3
redis[hiredis]~=7.1.0
rich~=13.6
ruamel.yaml~=0.18.10
SQLAlchemy[postgresql_asyncpg]~=2.0.45
setproctitle~=1.3.5
setproctitle~=1.3.7
setuptools~=80.0.0
strawberry-graphql~=0.278.0
sniffio~=1.3.1
strawberry-graphql~=0.287.2
tabulate~=0.8.9
temporenc~=0.1.0
tenacity>=9.0
tenacity~=9.0
toml~=0.10.2
tomli~=2.0.1
tomli-w~=1.2.0
Expand All @@ -98,14 +100,14 @@ typing_extensions~=4.11
textual~=0.79.1
uvloop~=0.22.1; sys_platform != "Windows"
valkey-glide~=2.2.2
yarl~=1.19.0
yarl~=1.22.0
zipstream-new~=1.1.8

# required by ai.backend.test (integration test suite)
pytest>=8.3.3
pytest~=8.3.3
pytest-aiohttp~=1.1.0
pytest-dependency>=0.6.0
pytest-mock>=3.14.0
pytest-dependency~=0.6.0
pytest-mock~=3.14.0
testcontainers[postgres,redis,minio]~=4.8.1

# type stubs
Expand Down
98 changes: 98 additions & 0 deletions scripts/fetch-ruff-version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "httpx",
# ]
# ///
"""
Fetch Ruff release information and generate pants.toml known_versions entries.

Usage:
uv run scripts/fetch-ruff-version.py 0.14.8
"""
from __future__ import annotations

import argparse
import sys

import httpx

# Mapping from Ruff release asset names to pants platform names
PLATFORM_MAPPING = {
"aarch64-apple-darwin": "macos_arm64",
"x86_64-apple-darwin": "macos_x86_64",
"aarch64-unknown-linux-musl": "linux_arm64",
"x86_64-unknown-linux-musl": "linux_x86_64",
}

BASE_URL = "https://github.com/astral-sh/ruff/releases/download"


def fetch_asset_info(version: str, ruff_platform: str) -> tuple[str, int]:
"""Fetch SHA256 checksum and file size for a specific asset."""
tarball_url = f"{BASE_URL}/{version}/ruff-{ruff_platform}.tar.gz"
checksum_url = f"{tarball_url}.sha256"

with httpx.Client(follow_redirects=True, timeout=30.0) as client:
# Fetch checksum
checksum_response = client.get(checksum_url)
checksum_response.raise_for_status()
# The .sha256 file contains: "checksum filename" or just "checksum"
checksum_text = checksum_response.text.strip()
sha256 = checksum_text.split()[0]

# Fetch file size via HEAD request
head_response = client.head(tarball_url)
head_response.raise_for_status()
size = int(head_response.headers["content-length"])

return sha256, size


def main() -> int:
parser = argparse.ArgumentParser(
description="Fetch Ruff release info and generate pants.toml known_versions entries"
)
parser.add_argument(
"version",
help="Ruff version number (e.g., 0.14.8)",
)
args = parser.parse_args()

version = args.version

print(f"Fetching release info for Ruff {version}...", file=sys.stderr)
print(file=sys.stderr)

entries: list[str] = []

for ruff_platform, pants_platform in PLATFORM_MAPPING.items():
try:
sha256, size = fetch_asset_info(version, ruff_platform)
entry = f' "{version}|{pants_platform}|{sha256}|{size}",'
entries.append(entry)
print(f" {pants_platform}: OK", file=sys.stderr)
except httpx.HTTPStatusError as e:
print(
f" {pants_platform}: FAILED ({e.response.status_code})",
file=sys.stderr,
)
return 1
except Exception as e:
print(f" {pants_platform}: ERROR ({e})", file=sys.stderr)
return 1

print(file=sys.stderr)
print("Copy the following to pants.toml [ruff] section:", file=sys.stderr)
print(file=sys.stderr)

print("known_versions = [")
for entry in entries:
print(entry)
print("]")

return 0


if __name__ == "__main__":
sys.exit(main())
2 changes: 1 addition & 1 deletion scripts/pyscript.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
PYVER="3.13.7"
PYVER="3.14.2"
if ! command -v uv >/dev/null 2>&1; then
curl -LsSf https://astral.sh/uv/install.sh | sh
if [ $SHELL = "/bin/fish" ]; then
Expand Down
2 changes: 1 addition & 1 deletion scripts/python.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
PYVER="3.13.7"
PYVER="3.14.2"
if ! command -v uv >/dev/null 2>&1; then
curl -LsSf https://astral.sh/uv/install.sh | sh
if [ $SHELL = "/bin/fish" ]; then
Expand Down
2 changes: 1 addition & 1 deletion src/ai/backend/agent/docker/kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def _write_chunks(
docker_info = await docker.system.info()
docker_version = docker_info["ServerVersion"]
major, _, patch = docker_version.split(".", maxsplit=2)
config = None
config: dict[str, Any] | None = None
if (int(major) == 23 and int(patch) < 8) or (
int(major) == 24 and int(patch) < 1
):
Expand Down
5 changes: 3 additions & 2 deletions src/ai/backend/common/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
import socket
import uuid
from collections.abc import Awaitable, Callable, Iterable
from ipaddress import IPv4Network, IPv6Network, ip_address
from ipaddress import _BaseAddress as BaseIPAddress
from ipaddress import _BaseNetwork as BaseIPNetwork
from ipaddress import ip_address
from pathlib import Path, PosixPath
from typing import Optional

Expand All @@ -33,6 +32,8 @@
"get_wsl_version",
)

type BaseIPNetwork = IPv4Network | IPv6Network

log = logging.getLogger(__spec__.name)


Expand Down
2 changes: 1 addition & 1 deletion src/ai/backend/manager/api/gql/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,5 +242,5 @@ def as_str(self) -> str:
mutation=Mutation,
subscription=Subscription,
config=StrawberryConfig(auto_camel_case=True),
enable_federation_2=True,
federation_version="2.11",
)
2 changes: 1 addition & 1 deletion tests/unit/agent/test_config_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ def __call__(
) -> RawConfigT: ...

@pytest.fixture
def make_raw_config() -> MakeRawConfig:
def make_raw_config(self) -> MakeRawConfig:
def _make(
scratch_type: ScratchType = ScratchType.HOSTDIR,
sandbox_type: ContainerSandboxType | None = None,
Expand Down
Loading
Loading