mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-10 13:45:44 +08:00
feat: bump Python minimum from 3.12 to 3.13, drop strenum backport (#14767)
Closes #14753 ## What changed | File | Change | |---|---| | `pyproject.toml` | `requires-python` → `>=3.13,<3.15`; remove `strenum==0.4.15` | | `Dockerfile` | `uv python install 3.13`, `uv sync --python 3.13` | | `.github/workflows/tests.yml` | `uv sync --python 3.13` on both matrix legs | | `CLAUDE.md` | dev setup command + requirements note updated | | `deepdoc/parser/mineru_parser.py` | `from strenum import StrEnum` → `from enum import StrEnum` | | `agent/tools/code_exec.py` | same | `StrEnum` has been in the stdlib since Python 3.11 — the `strenum` backport package is no longer needed once the floor is 3.13. ## Why uv.lock is not regenerated `uv lock --python 3.13` fails because: 1. The infiniflow/graspologic fork pins `numpy>=1.26.4,<2.0.0` 2. `tensorflow-cpu>=2.20.0` (the first release with cp313 wheels) depends on `ml-dtypes>=0.5.1`, which requires `numpy>=2.1.0` 3. These two constraints are irreconcilable on Python 3.13 The lockfile regeneration requires loosening the `numpy` upper bound in the `infiniflow/graspologic` fork. Once that fork commit is updated and the SHA in `pyproject.toml:49` is bumped, `uv lock --python 3.13` will succeed. ## RFC corrections Two claims in the original RFC (#14753) did not hold up under code review: - **"graspologic hard-blocks 3.13"** — the infiniflow fork at the pinned commit has no `<3.13` Python constraint. The blocker is the transitive `numpy<2.0.0` conflict with tensorflow-cpu's test dependency, not a direct Python version cap. - **"free-threading throughput gains for I/O-bound workload"** — Python 3.13 free-threading requires a special `--disable-gil` build and provides no benefit for async I/O code (the GIL is already released during I/O). The real motivation is forward compatibility and improved error messages.
This commit is contained in:
4
.github/workflows/tests.yml
vendored
4
.github/workflows/tests.yml
vendored
@@ -158,7 +158,7 @@ jobs:
|
||||
|
||||
- name: Run unit test
|
||||
run: |
|
||||
uv sync --python 3.12 --group test --frozen
|
||||
uv sync --python 3.13 --group test --frozen
|
||||
source .venv/bin/activate
|
||||
which pytest || echo "pytest not in PATH"
|
||||
echo "Start to run unit test"
|
||||
@@ -222,7 +222,7 @@ jobs:
|
||||
# Patch entrypoint.sh for coverage
|
||||
sed -i '/"\$PY" api\/ragflow_server.py \${INIT_SUPERUSER_ARGS} &/c\ echo "Ensuring coverage is installed..."\n "$PY" -m pip install coverage -i https://mirrors.aliyun.com/pypi/simple\n export COVERAGE_FILE=/ragflow/logs/.coverage\n echo "Starting ragflow_server with coverage..."\n "$PY" -m coverage run --source=./api/apps --omit="*/tests/*,*/migrations/*" -a api/ragflow_server.py ${INIT_SUPERUSER_ARGS} &' ./entrypoint.sh
|
||||
cd ..
|
||||
uv sync --python 3.12 --group test --frozen && uv pip install -e sdk/python
|
||||
uv sync --python 3.13 --group test --frozen && uv pip install -e sdk/python
|
||||
|
||||
|
||||
- name: Start ragflow:nightly for Infinity
|
||||
|
||||
@@ -51,7 +51,7 @@ RAGFlow is an open-source RAG (Retrieval-Augmented Generation) engine based on d
|
||||
|
||||
```bash
|
||||
# Install Python dependencies
|
||||
uv sync --python 3.12 --all-extras
|
||||
uv sync --python 3.13 --all-extras
|
||||
uv run python3 download_deps.py
|
||||
pre-commit install
|
||||
|
||||
@@ -118,7 +118,7 @@ RAGFlow supports switching between Elasticsearch (default) and Infinity:
|
||||
|
||||
## Development Environment Requirements
|
||||
|
||||
- Python 3.10-3.12
|
||||
- Python 3.10-3.13
|
||||
- Node.js >=18.20.4
|
||||
- Docker & Docker Compose
|
||||
- uv package manager
|
||||
|
||||
@@ -78,7 +78,7 @@ RUN --mount=type=bind,from=infiniflow/ragflow_deps:latest,source=/,target=/deps
|
||||
tar xzf "/deps/uv-${uv_arch}-unknown-linux-gnu.tar.gz" \
|
||||
&& cp "uv-${uv_arch}-unknown-linux-gnu/"* /usr/local/bin/ \
|
||||
&& rm -rf "uv-${uv_arch}-unknown-linux-gnu" \
|
||||
&& uv python install 3.12
|
||||
&& uv python install 3.13
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 \
|
||||
UV_HTTP_TIMEOUT=200 \
|
||||
@@ -147,7 +147,7 @@ RUN --mount=type=cache,id=ragflow_uv,target=/root/.cache/uv,sharing=locked \
|
||||
else \
|
||||
sed -i 's|mirrors.aliyun.com/pypi|pypi.org|g' uv.lock; \
|
||||
fi; \
|
||||
uv sync --python 3.12 --frozen && \
|
||||
uv sync --python 3.13 --frozen && \
|
||||
# Ensure pip is available in the venv for runtime package installation (fixes #12651)
|
||||
.venv/bin/python3 -m ensurepip --upgrade
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ from collections.abc import Mapping
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
from strenum import StrEnum
|
||||
from enum import StrEnum
|
||||
|
||||
from agent.tools.base import ToolBase, ToolMeta, ToolParamBase
|
||||
from api.db.services.file_service import FileService
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
|
||||
from enum import IntEnum
|
||||
from strenum import StrEnum
|
||||
from enum import StrEnum
|
||||
|
||||
|
||||
class UserTenantRole(StrEnum):
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import os
|
||||
from enum import Enum, IntEnum
|
||||
from strenum import StrEnum
|
||||
from enum import StrEnum
|
||||
|
||||
SERVICE_CONF = "service_conf.yaml"
|
||||
RAG_FLOW_SERVICE_NAME = "ragflow"
|
||||
|
||||
@@ -32,7 +32,7 @@ import numpy as np
|
||||
import pdfplumber
|
||||
import requests
|
||||
from PIL import Image
|
||||
from strenum import StrEnum
|
||||
from enum import StrEnum
|
||||
|
||||
from deepdoc.parser.pdf_parser import RAGFlowPdfParser
|
||||
from deepdoc.parser.utils import extract_pdf_outlines
|
||||
|
||||
@@ -32,7 +32,7 @@ from starlette.applications import Starlette
|
||||
from starlette.middleware import Middleware
|
||||
from starlette.responses import JSONResponse, Response
|
||||
from starlette.routing import Mount, Route
|
||||
from strenum import StrEnum
|
||||
from enum import StrEnum
|
||||
|
||||
|
||||
class LaunchMode(StrEnum):
|
||||
|
||||
@@ -5,8 +5,13 @@ description = "[RAGFlow](https://ragflow.io/) is an open-source RAG (Retrieval-A
|
||||
authors = [{ name = "Zhichang Yu", email = "yuzhichang@gmail.com" }]
|
||||
license-files = ["LICENSE"]
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12,<3.15"
|
||||
requires-python = ">=3.13,<3.15"
|
||||
dependencies = [
|
||||
# discord-py==2.3.2 unconditionally imports audioop in discord/player.py at module-
|
||||
# load time. audioop was removed from the CPython stdlib in Python 3.13 (PEP 594),
|
||||
# so any import of the discord package raises ImportError on Python 3.13 — even in
|
||||
# tests that never use voice features. audioop-lts provides the module as a backport.
|
||||
"audioop-lts>=0.2.1",
|
||||
"aiosmtplib>=5.0.0",
|
||||
"akshare>=1.15.78,<2.0.0",
|
||||
"anthropic==0.34.1",
|
||||
@@ -74,7 +79,7 @@ dependencies = [
|
||||
"opencv-python-headless==4.10.0.84",
|
||||
"opendal>=0.45.0,<0.46.0",
|
||||
"opensearch-py==2.7.1",
|
||||
"ormsgpack==1.5.0",
|
||||
"ormsgpack>=1.5.0",
|
||||
"pdfplumber==0.10.4",
|
||||
"pluginlib>=0.10.0",
|
||||
"psycopg2-binary>=2.9.11,<3.0.0",
|
||||
@@ -108,7 +113,6 @@ dependencies = [
|
||||
"agentrun-sdk>=0.0.16,<1.0.0",
|
||||
"nest-asyncio>=1.6.0,<2.0.0", # Needed for agent/component/message.py
|
||||
"sqlglotrs==0.9.0",
|
||||
"strenum==0.4.15",
|
||||
"tavily-python==0.5.1",
|
||||
"tencentcloud-sdk-python==3.0.1478",
|
||||
"tika==2.6.0",
|
||||
@@ -179,7 +183,6 @@ test = [
|
||||
"pycryptodomex==3.20.0",
|
||||
"pytest-playwright>=0.7.2",
|
||||
"codecov>=2.1.13",
|
||||
"tensorflow-cpu>=2.17.0",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
@@ -187,11 +190,31 @@ constraint-dependencies = [
|
||||
# CVE-2026-30922: Denial of Service via unbounded recursion in ASN.1 decoding (CVSS 7.5 HIGH)
|
||||
# pyasn1 < 0.6.3 is vulnerable; pulled in transitively via google-auth / rsa / pyasn1-modules
|
||||
"pyasn1>=0.6.3",
|
||||
# Python 3.13 added pathlib.PurePath.parser as a public class attribute holding
|
||||
# the posixpath/ntpath module. trio<0.26 introspects all Path class attributes to
|
||||
# generate async forwards and raises TypeError on any non-callable attribute it
|
||||
# encounters (fixed in trio 0.26 by skipping non-callables). Pulled in transitively
|
||||
# via selenium-wire -> trio-websocket -> trio.
|
||||
"trio>=0.26.0",
|
||||
]
|
||||
override-dependencies = [
|
||||
# moodlepy<=0.24.1 pins attrs<23.0.0, but trio>=0.26.0 requires attrs>=23.2.0.
|
||||
# attrs 23.x is backward-compatible; moodlepy works fine at runtime with it.
|
||||
"attrs>=23.2.0",
|
||||
]
|
||||
# trio 0.26+ (Python 3.13 compatible) is not yet on the Aliyun mirror.
|
||||
# Mark PyPI as explicit so it is used only for packages listed in [tool.uv.sources].
|
||||
[[tool.uv.index]]
|
||||
name = "pypi"
|
||||
url = "https://pypi.org/simple"
|
||||
explicit = true
|
||||
|
||||
[[tool.uv.index]]
|
||||
url = "https://mirrors.aliyun.com/pypi/simple"
|
||||
|
||||
[tool.uv.sources]
|
||||
trio = [{ index = "pypi" }]
|
||||
|
||||
[tool.setuptools]
|
||||
packages = [
|
||||
'agent',
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
import importlib
|
||||
import inspect
|
||||
|
||||
from strenum import StrEnum
|
||||
from enum import StrEnum
|
||||
|
||||
|
||||
class SupportedLiteLLMProvider(StrEnum):
|
||||
|
||||
@@ -28,7 +28,7 @@ import json_repair
|
||||
import litellm
|
||||
import openai
|
||||
from openai import AsyncOpenAI, OpenAI
|
||||
from strenum import StrEnum
|
||||
from enum import StrEnum
|
||||
|
||||
from common.misc_utils import thread_pool_exec
|
||||
from common.token_utils import num_tokens_from_string, total_token_count_from_response
|
||||
|
||||
@@ -123,7 +123,7 @@ def _load_session_module(monkeypatch):
|
||||
|
||||
# Mock common.constants module
|
||||
from enum import Enum
|
||||
from strenum import StrEnum
|
||||
from enum import StrEnum
|
||||
|
||||
class _StubLLMType(StrEnum):
|
||||
CHAT = "chat"
|
||||
|
||||
Reference in New Issue
Block a user