feat: Add support for Python 3.13 (#6685)

This commit is contained in:
Christophe Bornet 2025-02-20 19:13:21 +01:00 committed by GitHub
commit 41edba73c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 910 additions and 400 deletions

View file

@ -4,7 +4,7 @@ description: "Checks out code, installs uv, and sets up Python environment"
inputs:
python-version:
description: "Python version to use"
default: "3.12"
default: "3.13"
runs:
using: "composite"

View file

@ -24,7 +24,7 @@ jobs:
fetch-depth: 0
- name: "Setup Environment"
uses: ./.github/actions/setup-uv
- run: uv sync --extra dev
- run: uv sync
- name: Run Codeflash Optimizer
working-directory: ./src/backend/base
continue-on-error: true

View file

@ -306,7 +306,7 @@ jobs:
strategy:
matrix:
python-version:
- "3.12"
- "3.13"
steps:
- name: Check out the code at a specific ref
uses: actions/checkout@v4

View file

@ -13,7 +13,7 @@ on:
description: "(Optional) Python versions to test"
required: true
type: string
default: "['3.10', '3.11', '3.12']"
default: "['3.10', '3.11', '3.12', '3.13']"
ref:
description: "(Optional) ref to checkout"
required: false
@ -30,6 +30,7 @@ jobs:
max-parallel: 1 # Currently, we can only run at a time for collection-per-db-constraints
matrix:
python-version:
- "3.13"
- "3.12"
- "3.11"
- "3.10"

View file

@ -19,6 +19,7 @@ jobs:
strategy:
matrix:
python-version:
- "3.13"
- "3.12"
- "3.11"
- "3.10"

View file

@ -8,7 +8,7 @@ on:
env:
POETRY_VERSION: "1.8.3"
PYTHON_VERSION: "3.12"
PYTHON_VERSION: "3.13"
jobs:
create-nightly-tag:
@ -139,7 +139,7 @@ jobs:
needs: create-nightly-tag
uses: ./.github/workflows/python_test.yml
with:
python-versions: '["3.10", "3.11", "3.12"]'
python-versions: '["3.10", "3.11", "3.12", "3.13"]'
# Not making nightly builds dependent on integration test success
# due to inherent flakiness of 3rd party integrations
@ -149,7 +149,7 @@ jobs:
# needs: create-nightly-tag
# uses: ./.github/workflows/integration_tests.yml
# with:
# python-versions: '["3.10", "3.11", "3.12"]'
# python-versions: '["3.10", "3.11", "3.12", "3.13"]'
# ref: ${{ needs.create-nightly-tag.outputs.tag }}
release-nightly-build:

View file

@ -7,7 +7,7 @@ on:
description: "(Optional) Python versions to test"
required: true
type: string
default: "['3.10', '3.11', '3.12']"
default: "['3.10', '3.11', '3.12', '3.13']"
ref:
description: "(Optional) ref to checkout"
required: false
@ -23,7 +23,7 @@ on:
description: "(Optional) Python versions to test"
required: true
type: string
default: "['3.10', '3.11', '3.12']"
default: "['3.10', '3.11', '3.12', '3.13']"
env:
POETRY_VERSION: "1.8.2"
NODE_VERSION: "21"
@ -37,7 +37,7 @@ jobs:
UV_CACHE_DIR: /tmp/.uv-cache
strategy:
matrix:
python-version: ${{ fromJson(inputs.python-versions || '["3.10", "3.11", "3.12"]' ) }}
python-version: ${{ fromJson(inputs.python-versions || '["3.10", "3.11", "3.12", "3.13"]' ) }}
splitCount: [5]
group: [1, 2, 3, 4, 5]
steps:
@ -68,7 +68,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ${{ fromJson(inputs.python-versions || '["3.10", "3.11", "3.12"]' ) }}
python-version: ${{ fromJson(inputs.python-versions || '["3.10", "3.11", "3.12", "3.13"]' ) }}
steps:
- uses: actions/checkout@v4
with:
@ -88,7 +88,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ${{ fromJson(inputs.python-versions || '["3.10", "3.11", "3.12"]') }}
python-version: ${{ fromJson(inputs.python-versions || '["3.10", "3.11", "3.12", "3.13"]') }}
steps:
- name: Check out the code at a specific ref
uses: actions/checkout@v4

View file

@ -47,7 +47,7 @@ jobs:
name: CI
uses: ./.github/workflows/ci.yml
with:
python-versions: "['3.10', '3.11', '3.12']"
python-versions: "['3.10', '3.11', '3.12', '3.13']"
frontend-tests-folder: "tests"
release: true

View file

@ -55,7 +55,7 @@ on:
env:
POETRY_VERSION: "1.8.3"
PYTHON_VERSION: "3.12"
PYTHON_VERSION: "3.13"
jobs:
release-nightly-base:

View file

@ -13,7 +13,7 @@ jobs:
strategy:
matrix:
python-version:
- "3.12"
- "3.13"
steps:
- name: Check out the code at a specific ref
uses: actions/checkout@v4

View file

@ -51,7 +51,7 @@ on:
env:
NODE_VERSION: "21"
PYTHON_VERSION: "3.12"
PYTHON_VERSION: "3.13"
# Define the directory where Playwright browsers will be installed.
# Adjust if your project uses a different path.
PLAYWRIGHT_BROWSERS_PATH: "ms-playwright"

View file

@ -142,7 +142,7 @@ coverage: ## run the tests and generate a coverage report
@uv run coverage erase
unit_tests: ## run unit tests
@uv sync --extra dev --frozen
@uv sync --frozen
@EXTRA_ARGS=""
@if [ "$(async)" = "true" ]; then \
EXTRA_ARGS="$$EXTRA_ARGS --instafail -n auto"; \

View file

@ -3,7 +3,7 @@
name = "langflow"
version = "1.1.5"
description = "A Python package with a built-in web application"
requires-python = ">=3.10,<3.13"
requires-python = ">=3.10,<3.14"
license = "MIT"
keywords = ["nlp", "langchain", "openai", "gpt", "gui"]
readme = "README.md"
@ -26,7 +26,7 @@ dependencies = [
"huggingface-hub[inference]>=0.23.2,<1.0.0",
"networkx==3.4.2",
"fake-useragent==1.5.1",
"pyarrow==17.0.0",
"pyarrow==19.0.0",
"wikipedia==1.4.0",
"qdrant-client==1.9.2",
"weaviate-client==4.10.2",
@ -52,7 +52,7 @@ dependencies = [
"pytube==15.0.0",
"dspy-ai==2.5.41",
"assemblyai==0.35.1",
"litellm==1.59.8",
"litellm==1.60.2",
"chromadb==0.5.23",
"zep-python==2.0.2",
"youtube-transcript-api==0.6.3",
@ -105,7 +105,7 @@ dependencies = [
"sseclient-py==1.8.0",
"arize-phoenix-otel>=0.6.1",
"openinference-instrumentation-langchain>=0.1.29",
"crewai~=0.86.0",
"crewai==0.102.0",
"mcp>=0.9.1",
"uv>=0.5.7",
"ag2>=0.1.0",
@ -188,7 +188,7 @@ dev-dependencies = [
"asgi-lifespan>=2.1.0",
"pytest-github-actions-annotate-failures>=0.2.0",
"pytest-codspeed>=3.0.0",
"blockbuster>=1.5.18,<1.6",
"blockbuster>=1.5.20,<1.6",
"types-aiofiles>=24.1.0.20240626",
"codeflash>=0.8.4",
"hypothesis>=6.123.17",

View file

@ -597,8 +597,8 @@ async def load_flows_from_directory() -> None:
# Ensure that the default folder exists for this user
_ = await get_or_create_default_folder(session, user.id)
async for file_path in anyio.Path(flows_path).iterdir():
if not await file_path.is_file() or file_path.suffix != ".json":
for file_path in await asyncio.to_thread(Path(flows_path).iterdir):
if not await anyio.Path(file_path).is_file() or file_path.suffix != ".json":
continue
logger.info(f"Loading flow from file: {file_path.name}")
async with async_open(str(file_path), "r", encoding="utf-8") as f:

View file

@ -1,3 +1,6 @@
import asyncio
from pathlib import Path
import anyio
from aiofile import async_open
from loguru import logger
@ -88,7 +91,9 @@ class LocalStorageService(StorageService):
msg = f"Flow {flow_id} directory does not exist."
raise FileNotFoundError(msg)
files = [file.name async for file in folder_path.iterdir() if await file.is_file()]
files = [
file.name for file in await asyncio.to_thread(Path(folder_path).iterdir) if await anyio.Path(file).is_file()
]
logger.info(f"Listed {len(files)} files in flow {flow_id}.")
return files

View file

@ -108,14 +108,15 @@ def execute_function(code, function_name, *args, **kwargs):
)
function_code.parent = None
code_obj = compile(ast.Module(body=[function_code], type_ignores=[]), "<string>", "exec")
exec_locals = dict(locals())
try:
exec(code_obj, exec_globals, locals())
exec(code_obj, exec_globals, exec_locals)
except Exception as exc:
msg = "Function string does not contain a function"
raise ValueError(msg) from exc
# Add the function to the exec_globals dictionary
exec_globals[function_name] = locals()[function_name]
exec_globals[function_name] = exec_locals[function_name]
return exec_globals[function_name](*args, **kwargs)
@ -152,9 +153,10 @@ def create_function(code, function_name):
)
function_code.parent = None
code_obj = compile(ast.Module(body=[function_code], type_ignores=[]), "<string>", "exec")
exec_locals = dict(locals())
with contextlib.suppress(Exception):
exec(code_obj, exec_globals, locals())
exec_globals[function_name] = locals()[function_name]
exec(code_obj, exec_globals, exec_locals)
exec_globals[function_name] = exec_locals[function_name]
# Return a function that imports necessary modules and calls the target function
def wrapped_function(*args, **kwargs):
@ -306,8 +308,9 @@ def build_class_constructor(compiled_class, exec_globals, class_name):
Returns:
Constructor function for the class
"""
exec(compiled_class, exec_globals, locals())
exec_globals[class_name] = locals()[class_name]
exec_locals = dict(locals())
exec(compiled_class, exec_globals, exec_locals)
exec_globals[class_name] = exec_locals[class_name]
# Return a function that imports necessary modules and creates an instance of the target class
def build_custom_class():

View file

@ -2,7 +2,7 @@
name = "langflow-base"
version = "0.1.5"
description = "A Python package with a built-in web application"
requires-python = ">=3.10,<3.13"
requires-python = ">=3.10,<3.14"
license = "MIT"
keywords = ["nlp", "langchain", "openai", "gpt", "gui"]
readme = "README.md"
@ -37,7 +37,7 @@ dependencies = [
"cachetools>=5.5.0,<6.0.0",
"platformdirs>=4.2.0,<5.0.0",
"python-multipart>=0.0.12,<1.0.0",
"orjson==3.10.0",
"orjson==3.10.15",
"alembic>=1.13.0,<2.0.0",
"passlib>=1.7.4,<2.0.0",
"bcrypt==4.0.1",

1234
uv.lock generated

File diff suppressed because it is too large Load diff