From b3b8b6eb087d5f2f1700692bcb09df45cbfcc0ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leynier=20Guti=C3=A9rrez=20Gonz=C3=A1lez?= Date: Sat, 8 Aug 2026 18:38:22 -0600 Subject: [PATCH 1/2] fix: enforce the v0.5 Python baseline --- catalog/components.yml | 246 +++++++++--------- catalog/generated/catalog.json | 246 +++++++++--------- changelog.md | 59 ++++- copier.yml | 10 +- docs/reference/components.md | 246 +++++++++--------- template/pyproject.toml.jinja | 2 +- ..., 'hybrid'] %}training.py{% endif %}.jinja | 2 +- tests/test_catalog.py | 52 ++++ tests/test_generation.py | 4 +- tests/test_toolchain.py | 20 ++ 10 files changed, 506 insertions(+), 381 deletions(-) diff --git a/catalog/components.yml b/catalog/components.yml index beb2ad5..67a376c 100644 --- a/catalog/components.yml +++ b/catalog/components.yml @@ -7,57 +7,57 @@ components: name: Python library layer: workload tier: stable - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" - id: cli name: CLI application layer: workload tier: stable - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" - id: api name: API service layer: workload tier: stable - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" - id: web name: Python web application layer: workload tier: stable - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" - id: tui name: Terminal UI layer: workload tier: stable - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" - id: mcp name: MCP server layer: workload tier: stable - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" - id: agent name: AI agent layer: workload tier: stable - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" - id: rag name: RAG application layer: workload tier: stable - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" - id: inference name: Model inference service layer: workload tier: stable - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" - id: training name: Model training project layer: workload tier: stable - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" - id: hybrid name: Training and serving workspace layer: workload tier: stable - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" # Primary frameworks. Only one primary framework is selected per workload. - id: typer @@ -65,119 +65,119 @@ components: layer: framework tier: stable workloads: [cli] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["typer>=0.27.1,<1"] - id: fastapi name: FastAPI layer: framework tier: stable workloads: [api] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["fastapi[standard]>=0.141.1,<1", "pydantic>=2.13.4,<3", "uvicorn>=0.52.1,<1"] - id: flask name: Flask layer: framework tier: stable workloads: [api] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["flask>=3.1.2,<4"] - id: fastmcp name: FastMCP layer: framework tier: stable workloads: [mcp] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["fastmcp>=3.4.6,<4"] - id: pydantic-ai name: PydanticAI layer: framework tier: stable workloads: [agent] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["pydantic-ai>=2.27.0,<3"] - id: langgraph name: LangGraph layer: framework tier: stable workloads: [agent] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["langgraph>=1.2.10,<2"] - id: langchain name: LangChain layer: framework tier: stable workloads: [agent, rag] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["langchain>=1.3.14,<2"] - id: llamaindex name: LlamaIndex layer: framework tier: stable workloads: [agent, rag] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["llama-index>=0.14.23,<0.15"] - id: crewai name: CrewAI layer: framework tier: stable workloads: [agent] - python: ">=3.11,<3.14" + python: ">=3.12,<3.14" packages: ["crewai>=1.15.13,<2"] - id: smolagents name: Hugging Face smolagents layer: framework tier: stable workloads: [agent] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["smolagents>=1.26.0,<2"] - id: dspy name: DSPy layer: framework tier: stable workloads: [agent] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["dspy>=3.3.0,<4"] - id: openai-agents name: OpenAI Agents SDK layer: framework tier: platform workloads: [agent] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["openai-agents>=0.19.4,<1"] - id: google-adk name: Google ADK layer: framework tier: platform workloads: [agent] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["google-adk>=2.6.3,<3"] - id: strands-agents name: Strands Agents layer: framework tier: platform workloads: [agent] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["strands-agents>=1.51.0,<2"] - id: autogen name: Microsoft AutoGen layer: framework tier: stable workloads: [agent] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["autogen-agentchat>=0.7.5,<1"] - id: ag2 name: AG2 layer: framework tier: stable workloads: [agent] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["ag2>=1.0.1,<2"] - id: agno name: Agno layer: framework tier: stable workloads: [agent] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["agno>=2.8.7,<3"] - id: lingo name: Lingo @@ -191,149 +191,149 @@ components: layer: framework tier: stable workloads: [rag] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["haystack-ai>=3.0.0,<4"] - id: pytorch name: PyTorch layer: framework tier: stable workloads: [training, hybrid] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["torch>=2.13.0,<3"] - id: transformers name: Hugging Face Transformers layer: framework tier: stable workloads: [training, hybrid] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["transformers>=5.14.1,<6", "torch>=2.13.0,<3"] - id: jax name: JAX layer: framework tier: stable workloads: [training, hybrid] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["jax>=0.11.0,<0.12"] - id: keras name: Keras / TensorFlow layer: framework tier: stable workloads: [training, hybrid] - python: ">=3.11,<3.14" + python: ">=3.12,<3.14" packages: ["keras>=3.15.1,<4", "tensorflow>=2.21.0,<3"] - id: scikit-learn name: scikit-learn layer: framework tier: stable workloads: [training, hybrid] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["scikit-learn>=1.9.0,<2"] - id: xgboost name: XGBoost layer: framework tier: stable workloads: [training, hybrid] - python: ">=3.11,<3.15" + python: ">=3.12,<3.15" packages: ["xgboost>=3.4.0,<4"] # Interfaces are composable and can expose the same application through # multiple entrypoints. - - {id: streamlit, name: Streamlit, layer: interface, tier: stable, python: ">=3.11,<3.15", packages: ["streamlit>=1.61.1,<2"]} - - {id: gradio, name: Gradio, layer: interface, tier: stable, python: ">=3.11,<3.15", packages: ["gradio>=6.22.0,<7"]} - - {id: chainlit, name: Chainlit, layer: interface, tier: stable, python: ">=3.11,<3.14", packages: ["chainlit>=2.11.1,<3"]} - - {id: textual, name: Textual, layer: interface, tier: stable, python: ">=3.11,<3.15", packages: ["textual>=8.2.8,<9"]} - - {id: nicegui, name: NiceGUI, layer: interface, tier: stable, python: ">=3.11,<3.15", packages: ["nicegui>=3.15.0,<4"]} - - {id: fasthtml, name: FastHTML, layer: interface, tier: stable, python: ">=3.11,<3.15", packages: ["python-fasthtml>=0.14.11,<0.15"]} + - {id: streamlit, name: Streamlit, layer: interface, tier: stable, python: ">=3.12,<3.15", packages: ["streamlit>=1.61.1,<2"]} + - {id: gradio, name: Gradio, layer: interface, tier: stable, python: ">=3.12,<3.15", packages: ["gradio>=6.22.0,<7"]} + - {id: chainlit, name: Chainlit, layer: interface, tier: stable, python: ">=3.12,<3.14", packages: ["chainlit>=2.11.1,<3"]} + - {id: textual, name: Textual, layer: interface, tier: stable, python: ">=3.12,<3.15", packages: ["textual>=8.2.8,<9"]} + - {id: nicegui, name: NiceGUI, layer: interface, tier: stable, python: ">=3.12,<3.15", packages: ["nicegui>=3.15.0,<4"]} + - {id: fasthtml, name: FastHTML, layer: interface, tier: stable, python: ">=3.12,<3.15", packages: ["python-fasthtml>=0.14.11,<0.15"]} - {id: violetear, name: Violetear, layer: interface, tier: stable, python: ">=3.12,<3.15", packages: ["violetear[server]>=1.4.1,<2"]} - - {id: jupyterlab, name: JupyterLab, layer: interface, tier: stable, python: ">=3.11,<3.15", packages: ["jupyterlab>=4.6.2,<5"]} + - {id: jupyterlab, name: JupyterLab, layer: interface, tier: stable, python: ">=3.12,<3.15", packages: ["jupyterlab>=4.6.2,<5"]} # Providers are intentionally independent for generation and embeddings. - - {id: openai, name: OpenAI, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["openai>=2.53.0,<3"]} - - {id: anthropic, name: Anthropic, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["anthropic>=0.121.0,<1"]} - - {id: gemini, name: Google Gemini, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["google-genai>=2.17.0,<3"]} - - {id: azure-openai, name: Azure OpenAI, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["openai>=2.53.0,<3"]} - - {id: bedrock, name: AWS Bedrock, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["boto3>=1.43.67,<2"]} - - {id: openrouter, name: OpenRouter, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["openrouter>=1.1.37,<2"]} - - {id: groq, name: Groq, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["groq>=1.6.0,<2"]} - - {id: mistral, name: Mistral, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["mistralai>=2.9.1,<3"]} - - {id: cohere, name: Cohere, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["cohere>=7.0.8,<8"]} - - {id: huggingface, name: Hugging Face, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["huggingface-hub>=1.27.0,<2"]} - - {id: ollama, name: Ollama, layer: model_provider, tier: stable, python: ">=3.11,<3.15", packages: ["ollama>=0.6.2,<1"]} - - {id: openai-compatible, name: OpenAI-compatible endpoint, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["openai>=2.53.0,<3"]} - - {id: xai, name: xAI, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["xai-sdk>=1.17.0,<2"]} - - {id: deepseek, name: DeepSeek, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["openai>=2.53.0,<3"]} - - {id: together, name: Together AI, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["together>=2.30.0,<3"]} - - {id: fireworks, name: Fireworks AI, layer: model_provider, tier: platform, python: ">=3.11,<3.15", packages: ["fireworks-ai>=1.2.6,<2"]} - - {id: sentence-transformers, name: Sentence Transformers, layer: embedding_provider, tier: stable, python: ">=3.11,<3.15", packages: ["sentence-transformers>=5.7.0,<6"]} + - {id: openai, name: OpenAI, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["openai>=2.53.0,<3"]} + - {id: anthropic, name: Anthropic, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["anthropic>=0.121.0,<1"]} + - {id: gemini, name: Google Gemini, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["google-genai>=2.17.0,<3"]} + - {id: azure-openai, name: Azure OpenAI, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["openai>=2.53.0,<3"]} + - {id: bedrock, name: AWS Bedrock, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["boto3>=1.43.67,<2"]} + - {id: openrouter, name: OpenRouter, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["openrouter>=1.1.37,<2"]} + - {id: groq, name: Groq, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["groq>=1.6.0,<2"]} + - {id: mistral, name: Mistral, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["mistralai>=2.9.1,<3"]} + - {id: cohere, name: Cohere, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["cohere>=7.0.8,<8"]} + - {id: huggingface, name: Hugging Face, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["huggingface-hub>=1.27.0,<2"]} + - {id: ollama, name: Ollama, layer: model_provider, tier: stable, python: ">=3.12,<3.15", packages: ["ollama>=0.6.2,<1"]} + - {id: openai-compatible, name: OpenAI-compatible endpoint, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["openai>=2.53.0,<3"]} + - {id: xai, name: xAI, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["xai-sdk>=1.17.0,<2"]} + - {id: deepseek, name: DeepSeek, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["openai>=2.53.0,<3"]} + - {id: together, name: Together AI, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["together>=2.30.0,<3"]} + - {id: fireworks, name: Fireworks AI, layer: model_provider, tier: platform, python: ">=3.12,<3.15", packages: ["fireworks-ai>=1.2.6,<2"]} + - {id: sentence-transformers, name: Sentence Transformers, layer: embedding_provider, tier: stable, python: ">=3.12,<3.15", packages: ["sentence-transformers>=5.7.0,<6"]} # Data engines. A project may select at most one provider for each role. - - {id: sqlite, name: SQLite, layer: data, tier: stable, roles: [sql], python: ">=3.11,<3.15"} - - {id: postgresql, name: PostgreSQL, layer: data, tier: stable, roles: [sql], python: ">=3.11,<3.15", packages: ["psycopg[binary]>=3.3.4,<4"]} - - {id: mysql, name: MySQL, layer: data, tier: stable, roles: [sql], python: ">=3.11,<3.15", packages: ["pymysql>=1.2.0,<2"]} - - {id: duckdb, name: DuckDB, layer: data, tier: stable, roles: [sql], python: ">=3.11,<3.15", packages: ["duckdb>=1.5.5,<2", "duckdb-engine>=0.17.0,<1"]} - - {id: supabase, name: Supabase, layer: data, tier: platform, roles: [sql, document], python: ">=3.11,<3.15", packages: ["supabase>=2.31.0,<3"]} - - {id: mongodb, name: MongoDB, layer: data, tier: stable, roles: [document], python: ">=3.11,<3.15", packages: ["pymongo>=4.17.0,<5"]} + - {id: sqlite, name: SQLite, layer: data, tier: stable, roles: [sql], python: ">=3.12,<3.15"} + - {id: postgresql, name: PostgreSQL, layer: data, tier: stable, roles: [sql], python: ">=3.12,<3.15", packages: ["psycopg[binary]>=3.3.4,<4"]} + - {id: mysql, name: MySQL, layer: data, tier: stable, roles: [sql], python: ">=3.12,<3.15", packages: ["pymysql>=1.2.0,<2"]} + - {id: duckdb, name: DuckDB, layer: data, tier: stable, roles: [sql], python: ">=3.12,<3.15", packages: ["duckdb>=1.5.5,<2", "duckdb-engine>=0.17.0,<1"]} + - {id: supabase, name: Supabase, layer: data, tier: platform, roles: [sql, document], python: ">=3.12,<3.15", packages: ["supabase>=2.31.0,<3"]} + - {id: mongodb, name: MongoDB, layer: data, tier: stable, roles: [document], python: ">=3.12,<3.15", packages: ["pymongo>=4.17.0,<5"]} - {id: beaver, name: Beaver, layer: data, tier: stable, roles: [document, vector, graph, cache], python: ">=3.12,<3.15", packages: ["beaver-db>=2.3.0,<3"]} - - {id: pgvector, name: pgvector, layer: data, tier: stable, roles: [vector], python: ">=3.11,<3.15", packages: ["pgvector>=0.5.0,<1"]} - - {id: qdrant, name: Qdrant, layer: data, tier: stable, roles: [vector], python: ">=3.11,<3.15", packages: ["qdrant-client>=1.19.0,<2"]} - - {id: chroma, name: Chroma, layer: data, tier: stable, roles: [vector], python: ">=3.11,<3.15", packages: ["chromadb>=1.5.9,<2"]} - - {id: lancedb, name: LanceDB, layer: data, tier: stable, roles: [vector], python: ">=3.11,<3.15", packages: ["lancedb>=0.36.0,<1"]} - - {id: weaviate, name: Weaviate, layer: data, tier: platform, roles: [vector], python: ">=3.11,<3.15", packages: ["weaviate-client>=4.22.0,<5"]} - - {id: pinecone, name: Pinecone, layer: data, tier: platform, roles: [vector], python: ">=3.11,<3.15", packages: ["pinecone>=9.1.0,<10"]} - - {id: milvus, name: Milvus, layer: data, tier: stable, roles: [vector], python: ">=3.11,<3.15", packages: ["pymilvus>=3.0.1,<4"]} - - {id: neo4j, name: Neo4j, layer: data, tier: stable, roles: [graph], python: ">=3.11,<3.15", packages: ["neo4j>=6.2.0,<7"]} - - {id: redis, name: Redis, layer: data, tier: stable, roles: [cache], python: ">=3.11,<3.15", packages: ["redis>=8.1.0,<9"]} + - {id: pgvector, name: pgvector, layer: data, tier: stable, roles: [vector], python: ">=3.12,<3.15", packages: ["pgvector>=0.5.0,<1"]} + - {id: qdrant, name: Qdrant, layer: data, tier: stable, roles: [vector], python: ">=3.12,<3.15", packages: ["qdrant-client>=1.19.0,<2"]} + - {id: chroma, name: Chroma, layer: data, tier: stable, roles: [vector], python: ">=3.12,<3.15", packages: ["chromadb>=1.5.9,<2"]} + - {id: lancedb, name: LanceDB, layer: data, tier: stable, roles: [vector], python: ">=3.12,<3.15", packages: ["lancedb>=0.36.0,<1"]} + - {id: weaviate, name: Weaviate, layer: data, tier: platform, roles: [vector], python: ">=3.12,<3.15", packages: ["weaviate-client>=4.22.0,<5"]} + - {id: pinecone, name: Pinecone, layer: data, tier: platform, roles: [vector], python: ">=3.12,<3.15", packages: ["pinecone>=9.1.0,<10"]} + - {id: milvus, name: Milvus, layer: data, tier: stable, roles: [vector], python: ">=3.12,<3.15", packages: ["pymilvus>=3.0.1,<4"]} + - {id: neo4j, name: Neo4j, layer: data, tier: stable, roles: [graph], python: ">=3.12,<3.15", packages: ["neo4j>=6.2.0,<7"]} + - {id: redis, name: Redis, layer: data, tier: stable, roles: [cache], python: ">=3.12,<3.15", packages: ["redis>=8.1.0,<9"]} - - {id: sqlmodel, name: SQLModel, layer: sql_abstraction, tier: stable, python: ">=3.11,<3.15", packages: ["sqlmodel>=0.0.39,<0.1", "sqlalchemy>=2.0.51,<3", "alembic>=1.19.1,<2"]} - - {id: sqlalchemy, name: SQLAlchemy, layer: sql_abstraction, tier: stable, python: ">=3.11,<3.15", packages: ["sqlalchemy>=2.0.51,<3", "alembic>=1.19.1,<2"]} - - {id: api-key, name: API key, layer: auth, tier: stable, python: ">=3.11,<3.15"} - - {id: oidc, name: OAuth / OIDC, layer: auth, tier: platform, python: ">=3.11,<3.15", packages: ["authlib>=1.7.2,<2"]} - - {id: supabase-auth, name: Supabase Auth, layer: auth, tier: platform, python: ">=3.11,<3.15", packages: ["supabase>=2.31.0,<3"]} + - {id: sqlmodel, name: SQLModel, layer: sql_abstraction, tier: stable, python: ">=3.12,<3.15", packages: ["sqlmodel>=0.0.39,<0.1", "sqlalchemy>=2.0.51,<3", "alembic>=1.19.1,<2"]} + - {id: sqlalchemy, name: SQLAlchemy, layer: sql_abstraction, tier: stable, python: ">=3.12,<3.15", packages: ["sqlalchemy>=2.0.51,<3", "alembic>=1.19.1,<2"]} + - {id: api-key, name: API key, layer: auth, tier: stable, python: ">=3.12,<3.15"} + - {id: oidc, name: OAuth / OIDC, layer: auth, tier: platform, python: ">=3.12,<3.15", packages: ["authlib>=1.7.2,<2"]} + - {id: supabase-auth, name: Supabase Auth, layer: auth, tier: platform, python: ">=3.12,<3.15", packages: ["supabase>=2.31.0,<3"]} - - {id: bentoml, name: BentoML, layer: serving, tier: stable, python: ">=3.11,<3.15", packages: ["bentoml>=1.4.39,<2"]} - - {id: litellm, name: LiteLLM, layer: serving, tier: stable, python: ">=3.11,<3.15", packages: ["litellm>=1.95.0,<2"]} - - {id: vllm, name: vLLM, layer: serving, tier: platform, python: ">=3.11,<3.14", packages: ["vllm>=0.26.0,<0.27"]} - - {id: ollama-serving, name: Ollama, layer: serving, tier: stable, python: ">=3.11,<3.15", packages: ["ollama>=0.6.2,<1"]} - - {id: ray-serve, name: Ray Serve, layer: serving, tier: stable, python: ">=3.11,<3.15", packages: ["ray[serve]>=2.56.1,<3"]} + - {id: bentoml, name: BentoML, layer: serving, tier: stable, python: ">=3.12,<3.15", packages: ["bentoml>=1.4.39,<2"]} + - {id: litellm, name: LiteLLM, layer: serving, tier: stable, python: ">=3.12,<3.15", packages: ["litellm>=1.95.0,<2"]} + - {id: vllm, name: vLLM, layer: serving, tier: platform, python: ">=3.12,<3.14", packages: ["vllm>=0.26.0,<0.27"]} + - {id: ollama-serving, name: Ollama, layer: serving, tier: stable, python: ">=3.12,<3.15", packages: ["ollama>=0.6.2,<1"]} + - {id: ray-serve, name: Ray Serve, layer: serving, tier: stable, python: ">=3.12,<3.15", packages: ["ray[serve]>=2.56.1,<3"]} - - {id: lightning, name: Lightning, layer: training_extension, tier: stable, python: ">=3.11,<3.15", packages: ["lightning>=2.6.5,<3"]} - - {id: datasets, name: Hugging Face Datasets, layer: training_extension, tier: stable, python: ">=3.11,<3.15", packages: ["datasets>=5.0.1,<6"]} - - {id: accelerate, name: Accelerate, layer: training_extension, tier: stable, python: ">=3.11,<3.15", packages: ["accelerate>=1.14.0,<2"]} - - {id: peft, name: PEFT, layer: training_extension, tier: stable, python: ">=3.11,<3.15", packages: ["peft>=0.20.0,<0.21"]} - - {id: trl, name: TRL, layer: training_extension, tier: stable, python: ">=3.11,<3.15", packages: ["trl>=1.9.2,<2"]} - - {id: optuna, name: Optuna, layer: training_extension, tier: stable, python: ">=3.11,<3.15", packages: ["optuna>=4.9.0,<5"]} - - {id: prefect, name: Prefect, layer: mlops, tier: stable, python: ">=3.11,<3.15", packages: ["prefect>=3.8.2,<4"]} - - {id: dagster, name: Dagster, layer: mlops, tier: stable, python: ">=3.11,<3.15", packages: ["dagster>=1.13.17,<2"]} - - {id: temporal, name: Temporal, layer: mlops, tier: stable, python: ">=3.11,<3.15", packages: ["temporalio>=1.31.0,<2"]} - - {id: celery, name: Celery, layer: mlops, tier: stable, python: ">=3.11,<3.15", packages: ["celery>=5.6.3,<6"]} - - {id: dvc, name: DVC, layer: mlops, tier: stable, python: ">=3.11,<3.15", packages: ["dvc>=3.67.1,<4"]} - - {id: feast, name: Feast, layer: mlops, tier: stable, python: ">=3.11,<3.15", packages: ["feast>=0.65.0,<1"]} - - {id: evidently, name: Evidently, layer: mlops, tier: stable, python: ">=3.11,<3.15", packages: ["evidently>=0.7.21,<1"]} - - {id: polars, name: Polars, layer: mlops, tier: stable, python: ">=3.11,<3.15", packages: ["polars>=1.43.2,<2"]} - - {id: pandera, name: Pandera, layer: mlops, tier: stable, python: ">=3.11,<3.15", packages: ["pandera>=0.32.1,<0.33"]} + - {id: lightning, name: Lightning, layer: training_extension, tier: stable, python: ">=3.12,<3.15", packages: ["lightning>=2.6.5,<3"]} + - {id: datasets, name: Hugging Face Datasets, layer: training_extension, tier: stable, python: ">=3.12,<3.15", packages: ["datasets>=5.0.1,<6"]} + - {id: accelerate, name: Accelerate, layer: training_extension, tier: stable, python: ">=3.12,<3.15", packages: ["accelerate>=1.14.0,<2"]} + - {id: peft, name: PEFT, layer: training_extension, tier: stable, python: ">=3.12,<3.15", packages: ["peft>=0.20.0,<0.21"]} + - {id: trl, name: TRL, layer: training_extension, tier: stable, python: ">=3.12,<3.15", packages: ["trl>=1.9.2,<2"]} + - {id: optuna, name: Optuna, layer: training_extension, tier: stable, python: ">=3.12,<3.15", packages: ["optuna>=4.9.0,<5"]} + - {id: prefect, name: Prefect, layer: mlops, tier: stable, python: ">=3.12,<3.15", packages: ["prefect>=3.8.2,<4"]} + - {id: dagster, name: Dagster, layer: mlops, tier: stable, python: ">=3.12,<3.15", packages: ["dagster>=1.13.17,<2"]} + - {id: temporal, name: Temporal, layer: mlops, tier: stable, python: ">=3.12,<3.15", packages: ["temporalio>=1.31.0,<2"]} + - {id: celery, name: Celery, layer: mlops, tier: stable, python: ">=3.12,<3.15", packages: ["celery>=5.6.3,<6"]} + - {id: dvc, name: DVC, layer: mlops, tier: stable, python: ">=3.12,<3.15", packages: ["dvc>=3.67.1,<4"]} + - {id: feast, name: Feast, layer: mlops, tier: stable, python: ">=3.12,<3.15", packages: ["feast>=0.65.0,<1"]} + - {id: evidently, name: Evidently, layer: mlops, tier: stable, python: ">=3.12,<3.15", packages: ["evidently>=0.7.21,<1"]} + - {id: polars, name: Polars, layer: mlops, tier: stable, python: ">=3.12,<3.15", packages: ["polars>=1.43.2,<2"]} + - {id: pandera, name: Pandera, layer: mlops, tier: stable, python: ">=3.12,<3.15", packages: ["pandera>=0.32.1,<0.33"]} - - {id: deepeval, name: DeepEval, layer: quality, tier: stable, python: ">=3.11,<3.15", packages: ["deepeval>=4.1.5,<5"]} - - {id: ragas, name: Ragas, layer: quality, tier: stable, python: ">=3.11,<3.15", packages: ["ragas>=0.4.3,<0.5"]} - - {id: pydantic-evals, name: Pydantic Evals, layer: quality, tier: stable, python: ">=3.11,<3.15", packages: ["pydantic-evals>=2.27.0,<3"]} - - {id: opentelemetry, name: OpenTelemetry, layer: quality, tier: stable, python: ">=3.11,<3.15", packages: ["opentelemetry-sdk>=1.44.0,<2"]} - - {id: langfuse, name: Langfuse, layer: quality, tier: platform, python: ">=3.11,<3.15", packages: ["langfuse>=4.14.3,<5"]} - - {id: phoenix, name: Phoenix, layer: quality, tier: stable, python: ">=3.11,<3.15", packages: ["arize-phoenix>=19.19.1,<20"]} - - {id: mlflow, name: MLflow, layer: quality, tier: stable, python: ">=3.11,<3.15", packages: ["mlflow>=3.15.1,<4"]} - - {id: langsmith, name: LangSmith, layer: quality, tier: platform, python: ">=3.11,<3.15", packages: ["langsmith>=0.10.17,<0.11"]} - - {id: wandb, name: Weights & Biases, layer: quality, tier: platform, python: ">=3.11,<3.15", packages: ["wandb>=0.28.1,<0.29"]} + - {id: deepeval, name: DeepEval, layer: quality, tier: stable, python: ">=3.12,<3.15", packages: ["deepeval>=4.1.5,<5"]} + - {id: ragas, name: Ragas, layer: quality, tier: stable, python: ">=3.12,<3.15", packages: ["ragas>=0.4.3,<0.5"]} + - {id: pydantic-evals, name: Pydantic Evals, layer: quality, tier: stable, python: ">=3.12,<3.15", packages: ["pydantic-evals>=2.27.0,<3"]} + - {id: opentelemetry, name: OpenTelemetry, layer: quality, tier: stable, python: ">=3.12,<3.15", packages: ["opentelemetry-sdk>=1.44.0,<2"]} + - {id: langfuse, name: Langfuse, layer: quality, tier: platform, python: ">=3.12,<3.15", packages: ["langfuse>=4.14.3,<5"]} + - {id: phoenix, name: Phoenix, layer: quality, tier: stable, python: ">=3.12,<3.15", packages: ["arize-phoenix>=19.19.1,<20"]} + - {id: mlflow, name: MLflow, layer: quality, tier: stable, python: ">=3.12,<3.15", packages: ["mlflow>=3.15.1,<4"]} + - {id: langsmith, name: LangSmith, layer: quality, tier: platform, python: ">=3.12,<3.15", packages: ["langsmith>=0.10.17,<0.11"]} + - {id: wandb, name: Weights & Biases, layer: quality, tier: platform, python: ">=3.12,<3.15", packages: ["wandb>=0.28.1,<0.29"]} - - {id: docker, name: Docker / Compose, layer: deploy, tier: stable, python: ">=3.11,<3.15"} - - {id: render, name: Render, layer: deploy, tier: platform, python: ">=3.11,<3.15"} - - {id: fly, name: Fly.io, layer: deploy, tier: platform, python: ">=3.11,<3.15"} - - {id: vercel, name: Vercel, layer: deploy, tier: platform, python: ">=3.11,<3.15"} - - {id: railway, name: Railway, layer: deploy, tier: platform, python: ">=3.11,<3.15"} - - {id: hf-spaces, name: Hugging Face Spaces, layer: deploy, tier: platform, python: ">=3.11,<3.15"} - - {id: modal, name: Modal, layer: deploy, tier: platform, python: ">=3.11,<3.15", packages: ["modal>=1.5.3,<2"]} - - {id: runpod, name: RunPod, layer: deploy, tier: platform, python: ">=3.11,<3.15", packages: ["runpod>=1.11.0,<2"]} - - {id: bentocloud, name: BentoCloud, layer: deploy, tier: platform, python: ">=3.11,<3.15", packages: ["bentoml>=1.4.39,<2"]} - - {id: aws-ecs, name: AWS ECS, layer: deploy, tier: platform, python: ">=3.11,<3.15"} - - {id: aws-sagemaker, name: AWS SageMaker, layer: deploy, tier: platform, python: ">=3.11,<3.15"} - - {id: cloud-run, name: Google Cloud Run, layer: deploy, tier: platform, python: ">=3.11,<3.15"} - - {id: vertex-ai, name: Vertex AI, layer: deploy, tier: platform, python: ">=3.11,<3.15"} - - {id: azure-container-apps, name: Azure Container Apps, layer: deploy, tier: platform, python: ">=3.11,<3.15"} - - {id: azure-ml, name: Azure ML, layer: deploy, tier: platform, python: ">=3.11,<3.15"} + - {id: docker, name: Docker / Compose, layer: deploy, tier: stable, python: ">=3.12,<3.15"} + - {id: render, name: Render, layer: deploy, tier: platform, python: ">=3.12,<3.15"} + - {id: fly, name: Fly.io, layer: deploy, tier: platform, python: ">=3.12,<3.15"} + - {id: vercel, name: Vercel, layer: deploy, tier: platform, python: ">=3.12,<3.15"} + - {id: railway, name: Railway, layer: deploy, tier: platform, python: ">=3.12,<3.15"} + - {id: hf-spaces, name: Hugging Face Spaces, layer: deploy, tier: platform, python: ">=3.12,<3.15"} + - {id: modal, name: Modal, layer: deploy, tier: platform, python: ">=3.12,<3.15", packages: ["modal>=1.5.3,<2"]} + - {id: runpod, name: RunPod, layer: deploy, tier: platform, python: ">=3.12,<3.15", packages: ["runpod>=1.11.0,<2"]} + - {id: bentocloud, name: BentoCloud, layer: deploy, tier: platform, python: ">=3.12,<3.15", packages: ["bentoml>=1.4.39,<2"]} + - {id: aws-ecs, name: AWS ECS, layer: deploy, tier: platform, python: ">=3.12,<3.15"} + - {id: aws-sagemaker, name: AWS SageMaker, layer: deploy, tier: platform, python: ">=3.12,<3.15"} + - {id: cloud-run, name: Google Cloud Run, layer: deploy, tier: platform, python: ">=3.12,<3.15"} + - {id: vertex-ai, name: Vertex AI, layer: deploy, tier: platform, python: ">=3.12,<3.15"} + - {id: azure-container-apps, name: Azure Container Apps, layer: deploy, tier: platform, python: ">=3.12,<3.15"} + - {id: azure-ml, name: Azure ML, layer: deploy, tier: platform, python: ">=3.12,<3.15"} diff --git a/catalog/generated/catalog.json b/catalog/generated/catalog.json index a875365..2eebd97 100644 --- a/catalog/generated/catalog.json +++ b/catalog/generated/catalog.json @@ -6,7 +6,7 @@ "name": "Python library", "layer": "workload", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -16,7 +16,7 @@ "name": "CLI application", "layer": "workload", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -26,7 +26,7 @@ "name": "API service", "layer": "workload", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -36,7 +36,7 @@ "name": "Python web application", "layer": "workload", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -46,7 +46,7 @@ "name": "Terminal UI", "layer": "workload", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -56,7 +56,7 @@ "name": "MCP server", "layer": "workload", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -66,7 +66,7 @@ "name": "AI agent", "layer": "workload", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -76,7 +76,7 @@ "name": "RAG application", "layer": "workload", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -86,7 +86,7 @@ "name": "Model inference service", "layer": "workload", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -96,7 +96,7 @@ "name": "Model training project", "layer": "workload", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -106,7 +106,7 @@ "name": "Training and serving workspace", "layer": "workload", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -116,7 +116,7 @@ "name": "Typer", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "cli" ], @@ -130,7 +130,7 @@ "name": "FastAPI", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "api" ], @@ -146,7 +146,7 @@ "name": "Flask", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "api" ], @@ -160,7 +160,7 @@ "name": "FastMCP", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "mcp" ], @@ -174,7 +174,7 @@ "name": "PydanticAI", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent" ], @@ -188,7 +188,7 @@ "name": "LangGraph", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent" ], @@ -202,7 +202,7 @@ "name": "LangChain", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent", "rag" @@ -217,7 +217,7 @@ "name": "LlamaIndex", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent", "rag" @@ -232,7 +232,7 @@ "name": "CrewAI", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.14", + "python": ">=3.12,<3.14", "workloads": [ "agent" ], @@ -246,7 +246,7 @@ "name": "Hugging Face smolagents", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent" ], @@ -260,7 +260,7 @@ "name": "DSPy", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent" ], @@ -274,7 +274,7 @@ "name": "OpenAI Agents SDK", "layer": "framework", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent" ], @@ -288,7 +288,7 @@ "name": "Google ADK", "layer": "framework", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent" ], @@ -302,7 +302,7 @@ "name": "Strands Agents", "layer": "framework", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent" ], @@ -316,7 +316,7 @@ "name": "Microsoft AutoGen", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent" ], @@ -330,7 +330,7 @@ "name": "AG2", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent" ], @@ -344,7 +344,7 @@ "name": "Agno", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "agent" ], @@ -372,7 +372,7 @@ "name": "Haystack", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "rag" ], @@ -386,7 +386,7 @@ "name": "PyTorch", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "training", "hybrid" @@ -401,7 +401,7 @@ "name": "Hugging Face Transformers", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "training", "hybrid" @@ -417,7 +417,7 @@ "name": "JAX", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "training", "hybrid" @@ -432,7 +432,7 @@ "name": "Keras / TensorFlow", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.14", + "python": ">=3.12,<3.14", "workloads": [ "training", "hybrid" @@ -448,7 +448,7 @@ "name": "scikit-learn", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "training", "hybrid" @@ -463,7 +463,7 @@ "name": "XGBoost", "layer": "framework", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [ "training", "hybrid" @@ -478,7 +478,7 @@ "name": "Streamlit", "layer": "interface", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -490,7 +490,7 @@ "name": "Gradio", "layer": "interface", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -502,7 +502,7 @@ "name": "Chainlit", "layer": "interface", "tier": "stable", - "python": ">=3.11,<3.14", + "python": ">=3.12,<3.14", "workloads": [], "roles": [], "packages": [ @@ -514,7 +514,7 @@ "name": "Textual", "layer": "interface", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -526,7 +526,7 @@ "name": "NiceGUI", "layer": "interface", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -538,7 +538,7 @@ "name": "FastHTML", "layer": "interface", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -562,7 +562,7 @@ "name": "JupyterLab", "layer": "interface", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -574,7 +574,7 @@ "name": "OpenAI", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -586,7 +586,7 @@ "name": "Anthropic", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -598,7 +598,7 @@ "name": "Google Gemini", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -610,7 +610,7 @@ "name": "Azure OpenAI", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -622,7 +622,7 @@ "name": "AWS Bedrock", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -634,7 +634,7 @@ "name": "OpenRouter", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -646,7 +646,7 @@ "name": "Groq", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -658,7 +658,7 @@ "name": "Mistral", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -670,7 +670,7 @@ "name": "Cohere", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -682,7 +682,7 @@ "name": "Hugging Face", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -694,7 +694,7 @@ "name": "Ollama", "layer": "model_provider", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -706,7 +706,7 @@ "name": "OpenAI-compatible endpoint", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -718,7 +718,7 @@ "name": "xAI", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -730,7 +730,7 @@ "name": "DeepSeek", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -742,7 +742,7 @@ "name": "Together AI", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -754,7 +754,7 @@ "name": "Fireworks AI", "layer": "model_provider", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -766,7 +766,7 @@ "name": "Sentence Transformers", "layer": "embedding_provider", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -778,7 +778,7 @@ "name": "SQLite", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "sql" @@ -790,7 +790,7 @@ "name": "PostgreSQL", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "sql" @@ -804,7 +804,7 @@ "name": "MySQL", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "sql" @@ -818,7 +818,7 @@ "name": "DuckDB", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "sql" @@ -833,7 +833,7 @@ "name": "Supabase", "layer": "data", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "sql", @@ -848,7 +848,7 @@ "name": "MongoDB", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "document" @@ -879,7 +879,7 @@ "name": "pgvector", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "vector" @@ -893,7 +893,7 @@ "name": "Qdrant", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "vector" @@ -907,7 +907,7 @@ "name": "Chroma", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "vector" @@ -921,7 +921,7 @@ "name": "LanceDB", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "vector" @@ -935,7 +935,7 @@ "name": "Weaviate", "layer": "data", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "vector" @@ -949,7 +949,7 @@ "name": "Pinecone", "layer": "data", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "vector" @@ -963,7 +963,7 @@ "name": "Milvus", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "vector" @@ -977,7 +977,7 @@ "name": "Neo4j", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "graph" @@ -991,7 +991,7 @@ "name": "Redis", "layer": "data", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [ "cache" @@ -1005,7 +1005,7 @@ "name": "SQLModel", "layer": "sql_abstraction", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1019,7 +1019,7 @@ "name": "SQLAlchemy", "layer": "sql_abstraction", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1032,7 +1032,7 @@ "name": "API key", "layer": "auth", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1042,7 +1042,7 @@ "name": "OAuth / OIDC", "layer": "auth", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1054,7 +1054,7 @@ "name": "Supabase Auth", "layer": "auth", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1066,7 +1066,7 @@ "name": "BentoML", "layer": "serving", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1078,7 +1078,7 @@ "name": "LiteLLM", "layer": "serving", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1090,7 +1090,7 @@ "name": "vLLM", "layer": "serving", "tier": "platform", - "python": ">=3.11,<3.14", + "python": ">=3.12,<3.14", "workloads": [], "roles": [], "packages": [ @@ -1102,7 +1102,7 @@ "name": "Ollama", "layer": "serving", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1114,7 +1114,7 @@ "name": "Ray Serve", "layer": "serving", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1126,7 +1126,7 @@ "name": "Lightning", "layer": "training_extension", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1138,7 +1138,7 @@ "name": "Hugging Face Datasets", "layer": "training_extension", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1150,7 +1150,7 @@ "name": "Accelerate", "layer": "training_extension", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1162,7 +1162,7 @@ "name": "PEFT", "layer": "training_extension", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1174,7 +1174,7 @@ "name": "TRL", "layer": "training_extension", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1186,7 +1186,7 @@ "name": "Optuna", "layer": "training_extension", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1198,7 +1198,7 @@ "name": "Prefect", "layer": "mlops", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1210,7 +1210,7 @@ "name": "Dagster", "layer": "mlops", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1222,7 +1222,7 @@ "name": "Temporal", "layer": "mlops", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1234,7 +1234,7 @@ "name": "Celery", "layer": "mlops", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1246,7 +1246,7 @@ "name": "DVC", "layer": "mlops", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1258,7 +1258,7 @@ "name": "Feast", "layer": "mlops", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1270,7 +1270,7 @@ "name": "Evidently", "layer": "mlops", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1282,7 +1282,7 @@ "name": "Polars", "layer": "mlops", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1294,7 +1294,7 @@ "name": "Pandera", "layer": "mlops", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1306,7 +1306,7 @@ "name": "DeepEval", "layer": "quality", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1318,7 +1318,7 @@ "name": "Ragas", "layer": "quality", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1330,7 +1330,7 @@ "name": "Pydantic Evals", "layer": "quality", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1342,7 +1342,7 @@ "name": "OpenTelemetry", "layer": "quality", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1354,7 +1354,7 @@ "name": "Langfuse", "layer": "quality", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1366,7 +1366,7 @@ "name": "Phoenix", "layer": "quality", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1378,7 +1378,7 @@ "name": "MLflow", "layer": "quality", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1390,7 +1390,7 @@ "name": "LangSmith", "layer": "quality", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1402,7 +1402,7 @@ "name": "Weights & Biases", "layer": "quality", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1414,7 +1414,7 @@ "name": "Docker / Compose", "layer": "deploy", "tier": "stable", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1424,7 +1424,7 @@ "name": "Render", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1434,7 +1434,7 @@ "name": "Fly.io", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1444,7 +1444,7 @@ "name": "Vercel", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1454,7 +1454,7 @@ "name": "Railway", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1464,7 +1464,7 @@ "name": "Hugging Face Spaces", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1474,7 +1474,7 @@ "name": "Modal", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1486,7 +1486,7 @@ "name": "RunPod", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1498,7 +1498,7 @@ "name": "BentoCloud", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [ @@ -1510,7 +1510,7 @@ "name": "AWS ECS", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1520,7 +1520,7 @@ "name": "AWS SageMaker", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1530,7 +1530,7 @@ "name": "Google Cloud Run", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1540,7 +1540,7 @@ "name": "Vertex AI", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1550,7 +1550,7 @@ "name": "Azure Container Apps", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] @@ -1560,7 +1560,7 @@ "name": "Azure ML", "layer": "deploy", "tier": "platform", - "python": ">=3.11,<3.15", + "python": ">=3.12,<3.15", "workloads": [], "roles": [], "packages": [] diff --git a/changelog.md b/changelog.md index a4e7bc5..7d3f3dc 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,62 @@ in particular whenever `ty` or Zensical, both still pre-1.0, change their APIs. ## [Unreleased] +## [0.5.0] - 2026-08-08 + +This is a breaking redesign of the generator. There is no automated migration +from v0.4 projects; generate a fresh project and move application code +deliberately. + +### Added + +- A declarative catalog with 126 workload, framework, interface, provider, data, + auth, training, serving, operations, quality, and deployment components. +- Twelve editable presets: three simple Python projects, FastMCP, four agent + stacks, hosted and local RAG/agent applications, a LiteLLM gateway, and a + Hugging Face fine-tuning workspace. +- FastMCP, Pydantic AI and optional Pydantic AI Harness capabilities; Google + ADK, Strands Agents, LangGraph, LangChain, LlamaIndex, CrewAI, smolagents, + DSPy, OpenAI Agents SDK, AutoGen, AG2, Agno, Lingo, and Haystack. +- Independent model and embedding provider choices, plus SQL, document, vector, + graph, and cache roles with one selected engine per role. Beaver can fill its + four supported local-first roles. +- Streamlit, Gradio, Chainlit, Textual, NiceGUI, FastHTML, Violetear, and + JupyterLab interfaces; API composition can additionally expose FastAPI or + Flask. +- SQLModel/SQLAlchemy with Alembic, Supabase, MongoDB, vector databases, Neo4j, + Redis, and API key, OIDC, or Supabase authentication. +- PyTorch, Transformers, JAX, Keras/TensorFlow, scikit-learn, and XGBoost + training projects; training extensions, five serving engines, MLOps tools, + evaluations, and observability choices. Hybrid projects use an uv workspace. +- A portable Docker contract and 15 deployment targets. AWS, Google Cloud, and + Azure targets can generate Pulumi or Terraform; Modal, RunPod, and BentoCloud + receive native Python adapters. +- Three installable repository Agent Skills and stack-aware skills inside every + generated project, discoverable with `npx skills`. +- Root Zensical documentation, strict documentation CI, and Vercel static-site + configuration for `python-template.leynier.dev`. + +### Changed + +- The former `project_type` switch is replaced by compatible composable layers. +- Python 3.12 is now the minimum generated-project version. +- The README, contribution guide, issue forms, GitHub description, homepage, + and topics now describe the layer model and current catalog. +- CI adds credential-free vertical slices for AI, data, ML, deployment, skills, + and repository documentation, while retaining Linux, macOS, and Windows + generated-project gates. + +### Removed + +- ODMantic, AutoGOAL, FastUI, and Reflex are deliberately outside the supported + catalog. FastUI and Reflex are archived upstream; the other two do not fit the + accepted v0.5 scope. + +### Migration + +None. v0.5 is intentionally incompatible with v0.4 answers and generated +layout. Start from a newly generated project. + ## [0.4.1] ### Changed @@ -88,6 +144,7 @@ with the previous version. None. This release is not backwards compatible with the Cookiecutter template and does not try to be. Generate a fresh project and move your code across. -[Unreleased]: https://github.com/leynier/python-template/compare/v0.4.1...HEAD +[Unreleased]: https://github.com/leynier/python-template/compare/v0.5.0...HEAD +[0.5.0]: https://github.com/leynier/python-template/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/leynier/python-template/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/leynier/python-template/compare/v0.3.1...v0.4.0 diff --git a/copier.yml b/copier.yml index 6b6e782..431db06 100644 --- a/copier.yml +++ b/copier.yml @@ -519,20 +519,16 @@ iac_provider: python_version: type: str - # 3.10 is deliberately not offered: it reaches end of life on 2026-10-31. - # Drop each version from this list as it approaches its EOL date, and add - # new ones once they are released. + # v0.5 deliberately starts at Python 3.12. Drop each version from this list + # as it approaches EOL, and add new ones once they are released. help: Minimum supported Python version default: "3.13" choices: - - "3.11" - "3.12" - "3.13" - "3.14" validator: >- - {% if (framework in ['lingo'] or 'violetear' in interfaces or 'beaver' in [document_store, vector_store, graph_store, cache_store]) and python_version == '3.11' %} - The selected stack requires Python 3.12 or newer - {% elif (framework in ['crewai', 'keras'] or 'chainlit' in interfaces or serving == 'vllm') and python_version == '3.14' %} + {% if (framework in ['crewai', 'keras'] or 'chainlit' in interfaces or serving == 'vllm') and python_version == '3.14' %} The selected stack currently requires Python 3.13 or older {% endif %} diff --git a/docs/reference/components.md b/docs/reference/components.md index e3b969a..683afb0 100644 --- a/docs/reference/components.md +++ b/docs/reference/components.md @@ -4,129 +4,129 @@ This reference is generated from `catalog/components.yml`. Do not edit it by han | Layer | Component | Support | Python | | --- | --- | --- | --- | -| `workload` | Python library (`library`) | `stable` | `>=3.11,<3.15` | -| `workload` | CLI application (`cli`) | `stable` | `>=3.11,<3.15` | -| `workload` | API service (`api`) | `stable` | `>=3.11,<3.15` | -| `workload` | Python web application (`web`) | `stable` | `>=3.11,<3.15` | -| `workload` | Terminal UI (`tui`) | `stable` | `>=3.11,<3.15` | -| `workload` | MCP server (`mcp`) | `stable` | `>=3.11,<3.15` | -| `workload` | AI agent (`agent`) | `stable` | `>=3.11,<3.15` | -| `workload` | RAG application (`rag`) | `stable` | `>=3.11,<3.15` | -| `workload` | Model inference service (`inference`) | `stable` | `>=3.11,<3.15` | -| `workload` | Model training project (`training`) | `stable` | `>=3.11,<3.15` | -| `workload` | Training and serving workspace (`hybrid`) | `stable` | `>=3.11,<3.15` | -| `framework` | Typer (`typer`) | `stable` | `>=3.11,<3.15` | -| `framework` | FastAPI (`fastapi`) | `stable` | `>=3.11,<3.15` | -| `framework` | Flask (`flask`) | `stable` | `>=3.11,<3.15` | -| `framework` | FastMCP (`fastmcp`) | `stable` | `>=3.11,<3.15` | -| `framework` | PydanticAI (`pydantic-ai`) | `stable` | `>=3.11,<3.15` | -| `framework` | LangGraph (`langgraph`) | `stable` | `>=3.11,<3.15` | -| `framework` | LangChain (`langchain`) | `stable` | `>=3.11,<3.15` | -| `framework` | LlamaIndex (`llamaindex`) | `stable` | `>=3.11,<3.15` | -| `framework` | CrewAI (`crewai`) | `stable` | `>=3.11,<3.14` | -| `framework` | Hugging Face smolagents (`smolagents`) | `stable` | `>=3.11,<3.15` | -| `framework` | DSPy (`dspy`) | `stable` | `>=3.11,<3.15` | -| `framework` | OpenAI Agents SDK (`openai-agents`) | `platform` | `>=3.11,<3.15` | -| `framework` | Google ADK (`google-adk`) | `platform` | `>=3.11,<3.15` | -| `framework` | Strands Agents (`strands-agents`) | `platform` | `>=3.11,<3.15` | -| `framework` | Microsoft AutoGen (`autogen`) | `stable` | `>=3.11,<3.15` | -| `framework` | AG2 (`ag2`) | `stable` | `>=3.11,<3.15` | -| `framework` | Agno (`agno`) | `stable` | `>=3.11,<3.15` | +| `workload` | Python library (`library`) | `stable` | `>=3.12,<3.15` | +| `workload` | CLI application (`cli`) | `stable` | `>=3.12,<3.15` | +| `workload` | API service (`api`) | `stable` | `>=3.12,<3.15` | +| `workload` | Python web application (`web`) | `stable` | `>=3.12,<3.15` | +| `workload` | Terminal UI (`tui`) | `stable` | `>=3.12,<3.15` | +| `workload` | MCP server (`mcp`) | `stable` | `>=3.12,<3.15` | +| `workload` | AI agent (`agent`) | `stable` | `>=3.12,<3.15` | +| `workload` | RAG application (`rag`) | `stable` | `>=3.12,<3.15` | +| `workload` | Model inference service (`inference`) | `stable` | `>=3.12,<3.15` | +| `workload` | Model training project (`training`) | `stable` | `>=3.12,<3.15` | +| `workload` | Training and serving workspace (`hybrid`) | `stable` | `>=3.12,<3.15` | +| `framework` | Typer (`typer`) | `stable` | `>=3.12,<3.15` | +| `framework` | FastAPI (`fastapi`) | `stable` | `>=3.12,<3.15` | +| `framework` | Flask (`flask`) | `stable` | `>=3.12,<3.15` | +| `framework` | FastMCP (`fastmcp`) | `stable` | `>=3.12,<3.15` | +| `framework` | PydanticAI (`pydantic-ai`) | `stable` | `>=3.12,<3.15` | +| `framework` | LangGraph (`langgraph`) | `stable` | `>=3.12,<3.15` | +| `framework` | LangChain (`langchain`) | `stable` | `>=3.12,<3.15` | +| `framework` | LlamaIndex (`llamaindex`) | `stable` | `>=3.12,<3.15` | +| `framework` | CrewAI (`crewai`) | `stable` | `>=3.12,<3.14` | +| `framework` | Hugging Face smolagents (`smolagents`) | `stable` | `>=3.12,<3.15` | +| `framework` | DSPy (`dspy`) | `stable` | `>=3.12,<3.15` | +| `framework` | OpenAI Agents SDK (`openai-agents`) | `platform` | `>=3.12,<3.15` | +| `framework` | Google ADK (`google-adk`) | `platform` | `>=3.12,<3.15` | +| `framework` | Strands Agents (`strands-agents`) | `platform` | `>=3.12,<3.15` | +| `framework` | Microsoft AutoGen (`autogen`) | `stable` | `>=3.12,<3.15` | +| `framework` | AG2 (`ag2`) | `stable` | `>=3.12,<3.15` | +| `framework` | Agno (`agno`) | `stable` | `>=3.12,<3.15` | | `framework` | Lingo (`lingo`) | `stable` | `>=3.12,<3.15` | -| `framework` | Haystack (`haystack`) | `stable` | `>=3.11,<3.15` | -| `framework` | PyTorch (`pytorch`) | `stable` | `>=3.11,<3.15` | -| `framework` | Hugging Face Transformers (`transformers`) | `stable` | `>=3.11,<3.15` | -| `framework` | JAX (`jax`) | `stable` | `>=3.11,<3.15` | -| `framework` | Keras / TensorFlow (`keras`) | `stable` | `>=3.11,<3.14` | -| `framework` | scikit-learn (`scikit-learn`) | `stable` | `>=3.11,<3.15` | -| `framework` | XGBoost (`xgboost`) | `stable` | `>=3.11,<3.15` | -| `interface` | Streamlit (`streamlit`) | `stable` | `>=3.11,<3.15` | -| `interface` | Gradio (`gradio`) | `stable` | `>=3.11,<3.15` | -| `interface` | Chainlit (`chainlit`) | `stable` | `>=3.11,<3.14` | -| `interface` | Textual (`textual`) | `stable` | `>=3.11,<3.15` | -| `interface` | NiceGUI (`nicegui`) | `stable` | `>=3.11,<3.15` | -| `interface` | FastHTML (`fasthtml`) | `stable` | `>=3.11,<3.15` | +| `framework` | Haystack (`haystack`) | `stable` | `>=3.12,<3.15` | +| `framework` | PyTorch (`pytorch`) | `stable` | `>=3.12,<3.15` | +| `framework` | Hugging Face Transformers (`transformers`) | `stable` | `>=3.12,<3.15` | +| `framework` | JAX (`jax`) | `stable` | `>=3.12,<3.15` | +| `framework` | Keras / TensorFlow (`keras`) | `stable` | `>=3.12,<3.14` | +| `framework` | scikit-learn (`scikit-learn`) | `stable` | `>=3.12,<3.15` | +| `framework` | XGBoost (`xgboost`) | `stable` | `>=3.12,<3.15` | +| `interface` | Streamlit (`streamlit`) | `stable` | `>=3.12,<3.15` | +| `interface` | Gradio (`gradio`) | `stable` | `>=3.12,<3.15` | +| `interface` | Chainlit (`chainlit`) | `stable` | `>=3.12,<3.14` | +| `interface` | Textual (`textual`) | `stable` | `>=3.12,<3.15` | +| `interface` | NiceGUI (`nicegui`) | `stable` | `>=3.12,<3.15` | +| `interface` | FastHTML (`fasthtml`) | `stable` | `>=3.12,<3.15` | | `interface` | Violetear (`violetear`) | `stable` | `>=3.12,<3.15` | -| `interface` | JupyterLab (`jupyterlab`) | `stable` | `>=3.11,<3.15` | -| `model_provider` | OpenAI (`openai`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | Anthropic (`anthropic`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | Google Gemini (`gemini`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | Azure OpenAI (`azure-openai`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | AWS Bedrock (`bedrock`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | OpenRouter (`openrouter`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | Groq (`groq`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | Mistral (`mistral`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | Cohere (`cohere`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | Hugging Face (`huggingface`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | Ollama (`ollama`) | `stable` | `>=3.11,<3.15` | -| `model_provider` | OpenAI-compatible endpoint (`openai-compatible`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | xAI (`xai`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | DeepSeek (`deepseek`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | Together AI (`together`) | `platform` | `>=3.11,<3.15` | -| `model_provider` | Fireworks AI (`fireworks`) | `platform` | `>=3.11,<3.15` | -| `embedding_provider` | Sentence Transformers (`sentence-transformers`) | `stable` | `>=3.11,<3.15` | -| `data` | SQLite (`sqlite`) | `stable` | `>=3.11,<3.15` | -| `data` | PostgreSQL (`postgresql`) | `stable` | `>=3.11,<3.15` | -| `data` | MySQL (`mysql`) | `stable` | `>=3.11,<3.15` | -| `data` | DuckDB (`duckdb`) | `stable` | `>=3.11,<3.15` | -| `data` | Supabase (`supabase`) | `platform` | `>=3.11,<3.15` | -| `data` | MongoDB (`mongodb`) | `stable` | `>=3.11,<3.15` | +| `interface` | JupyterLab (`jupyterlab`) | `stable` | `>=3.12,<3.15` | +| `model_provider` | OpenAI (`openai`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | Anthropic (`anthropic`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | Google Gemini (`gemini`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | Azure OpenAI (`azure-openai`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | AWS Bedrock (`bedrock`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | OpenRouter (`openrouter`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | Groq (`groq`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | Mistral (`mistral`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | Cohere (`cohere`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | Hugging Face (`huggingface`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | Ollama (`ollama`) | `stable` | `>=3.12,<3.15` | +| `model_provider` | OpenAI-compatible endpoint (`openai-compatible`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | xAI (`xai`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | DeepSeek (`deepseek`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | Together AI (`together`) | `platform` | `>=3.12,<3.15` | +| `model_provider` | Fireworks AI (`fireworks`) | `platform` | `>=3.12,<3.15` | +| `embedding_provider` | Sentence Transformers (`sentence-transformers`) | `stable` | `>=3.12,<3.15` | +| `data` | SQLite (`sqlite`) | `stable` | `>=3.12,<3.15` | +| `data` | PostgreSQL (`postgresql`) | `stable` | `>=3.12,<3.15` | +| `data` | MySQL (`mysql`) | `stable` | `>=3.12,<3.15` | +| `data` | DuckDB (`duckdb`) | `stable` | `>=3.12,<3.15` | +| `data` | Supabase (`supabase`) | `platform` | `>=3.12,<3.15` | +| `data` | MongoDB (`mongodb`) | `stable` | `>=3.12,<3.15` | | `data` | Beaver (`beaver`) | `stable` | `>=3.12,<3.15` | -| `data` | pgvector (`pgvector`) | `stable` | `>=3.11,<3.15` | -| `data` | Qdrant (`qdrant`) | `stable` | `>=3.11,<3.15` | -| `data` | Chroma (`chroma`) | `stable` | `>=3.11,<3.15` | -| `data` | LanceDB (`lancedb`) | `stable` | `>=3.11,<3.15` | -| `data` | Weaviate (`weaviate`) | `platform` | `>=3.11,<3.15` | -| `data` | Pinecone (`pinecone`) | `platform` | `>=3.11,<3.15` | -| `data` | Milvus (`milvus`) | `stable` | `>=3.11,<3.15` | -| `data` | Neo4j (`neo4j`) | `stable` | `>=3.11,<3.15` | -| `data` | Redis (`redis`) | `stable` | `>=3.11,<3.15` | -| `sql_abstraction` | SQLModel (`sqlmodel`) | `stable` | `>=3.11,<3.15` | -| `sql_abstraction` | SQLAlchemy (`sqlalchemy`) | `stable` | `>=3.11,<3.15` | -| `auth` | API key (`api-key`) | `stable` | `>=3.11,<3.15` | -| `auth` | OAuth / OIDC (`oidc`) | `platform` | `>=3.11,<3.15` | -| `auth` | Supabase Auth (`supabase-auth`) | `platform` | `>=3.11,<3.15` | -| `serving` | BentoML (`bentoml`) | `stable` | `>=3.11,<3.15` | -| `serving` | LiteLLM (`litellm`) | `stable` | `>=3.11,<3.15` | -| `serving` | vLLM (`vllm`) | `platform` | `>=3.11,<3.14` | -| `serving` | Ollama (`ollama-serving`) | `stable` | `>=3.11,<3.15` | -| `serving` | Ray Serve (`ray-serve`) | `stable` | `>=3.11,<3.15` | -| `training_extension` | Lightning (`lightning`) | `stable` | `>=3.11,<3.15` | -| `training_extension` | Hugging Face Datasets (`datasets`) | `stable` | `>=3.11,<3.15` | -| `training_extension` | Accelerate (`accelerate`) | `stable` | `>=3.11,<3.15` | -| `training_extension` | PEFT (`peft`) | `stable` | `>=3.11,<3.15` | -| `training_extension` | TRL (`trl`) | `stable` | `>=3.11,<3.15` | -| `training_extension` | Optuna (`optuna`) | `stable` | `>=3.11,<3.15` | -| `mlops` | Prefect (`prefect`) | `stable` | `>=3.11,<3.15` | -| `mlops` | Dagster (`dagster`) | `stable` | `>=3.11,<3.15` | -| `mlops` | Temporal (`temporal`) | `stable` | `>=3.11,<3.15` | -| `mlops` | Celery (`celery`) | `stable` | `>=3.11,<3.15` | -| `mlops` | DVC (`dvc`) | `stable` | `>=3.11,<3.15` | -| `mlops` | Feast (`feast`) | `stable` | `>=3.11,<3.15` | -| `mlops` | Evidently (`evidently`) | `stable` | `>=3.11,<3.15` | -| `mlops` | Polars (`polars`) | `stable` | `>=3.11,<3.15` | -| `mlops` | Pandera (`pandera`) | `stable` | `>=3.11,<3.15` | -| `quality` | DeepEval (`deepeval`) | `stable` | `>=3.11,<3.15` | -| `quality` | Ragas (`ragas`) | `stable` | `>=3.11,<3.15` | -| `quality` | Pydantic Evals (`pydantic-evals`) | `stable` | `>=3.11,<3.15` | -| `quality` | OpenTelemetry (`opentelemetry`) | `stable` | `>=3.11,<3.15` | -| `quality` | Langfuse (`langfuse`) | `platform` | `>=3.11,<3.15` | -| `quality` | Phoenix (`phoenix`) | `stable` | `>=3.11,<3.15` | -| `quality` | MLflow (`mlflow`) | `stable` | `>=3.11,<3.15` | -| `quality` | LangSmith (`langsmith`) | `platform` | `>=3.11,<3.15` | -| `quality` | Weights & Biases (`wandb`) | `platform` | `>=3.11,<3.15` | -| `deploy` | Docker / Compose (`docker`) | `stable` | `>=3.11,<3.15` | -| `deploy` | Render (`render`) | `platform` | `>=3.11,<3.15` | -| `deploy` | Fly.io (`fly`) | `platform` | `>=3.11,<3.15` | -| `deploy` | Vercel (`vercel`) | `platform` | `>=3.11,<3.15` | -| `deploy` | Railway (`railway`) | `platform` | `>=3.11,<3.15` | -| `deploy` | Hugging Face Spaces (`hf-spaces`) | `platform` | `>=3.11,<3.15` | -| `deploy` | Modal (`modal`) | `platform` | `>=3.11,<3.15` | -| `deploy` | RunPod (`runpod`) | `platform` | `>=3.11,<3.15` | -| `deploy` | BentoCloud (`bentocloud`) | `platform` | `>=3.11,<3.15` | -| `deploy` | AWS ECS (`aws-ecs`) | `platform` | `>=3.11,<3.15` | -| `deploy` | AWS SageMaker (`aws-sagemaker`) | `platform` | `>=3.11,<3.15` | -| `deploy` | Google Cloud Run (`cloud-run`) | `platform` | `>=3.11,<3.15` | -| `deploy` | Vertex AI (`vertex-ai`) | `platform` | `>=3.11,<3.15` | -| `deploy` | Azure Container Apps (`azure-container-apps`) | `platform` | `>=3.11,<3.15` | -| `deploy` | Azure ML (`azure-ml`) | `platform` | `>=3.11,<3.15` | +| `data` | pgvector (`pgvector`) | `stable` | `>=3.12,<3.15` | +| `data` | Qdrant (`qdrant`) | `stable` | `>=3.12,<3.15` | +| `data` | Chroma (`chroma`) | `stable` | `>=3.12,<3.15` | +| `data` | LanceDB (`lancedb`) | `stable` | `>=3.12,<3.15` | +| `data` | Weaviate (`weaviate`) | `platform` | `>=3.12,<3.15` | +| `data` | Pinecone (`pinecone`) | `platform` | `>=3.12,<3.15` | +| `data` | Milvus (`milvus`) | `stable` | `>=3.12,<3.15` | +| `data` | Neo4j (`neo4j`) | `stable` | `>=3.12,<3.15` | +| `data` | Redis (`redis`) | `stable` | `>=3.12,<3.15` | +| `sql_abstraction` | SQLModel (`sqlmodel`) | `stable` | `>=3.12,<3.15` | +| `sql_abstraction` | SQLAlchemy (`sqlalchemy`) | `stable` | `>=3.12,<3.15` | +| `auth` | API key (`api-key`) | `stable` | `>=3.12,<3.15` | +| `auth` | OAuth / OIDC (`oidc`) | `platform` | `>=3.12,<3.15` | +| `auth` | Supabase Auth (`supabase-auth`) | `platform` | `>=3.12,<3.15` | +| `serving` | BentoML (`bentoml`) | `stable` | `>=3.12,<3.15` | +| `serving` | LiteLLM (`litellm`) | `stable` | `>=3.12,<3.15` | +| `serving` | vLLM (`vllm`) | `platform` | `>=3.12,<3.14` | +| `serving` | Ollama (`ollama-serving`) | `stable` | `>=3.12,<3.15` | +| `serving` | Ray Serve (`ray-serve`) | `stable` | `>=3.12,<3.15` | +| `training_extension` | Lightning (`lightning`) | `stable` | `>=3.12,<3.15` | +| `training_extension` | Hugging Face Datasets (`datasets`) | `stable` | `>=3.12,<3.15` | +| `training_extension` | Accelerate (`accelerate`) | `stable` | `>=3.12,<3.15` | +| `training_extension` | PEFT (`peft`) | `stable` | `>=3.12,<3.15` | +| `training_extension` | TRL (`trl`) | `stable` | `>=3.12,<3.15` | +| `training_extension` | Optuna (`optuna`) | `stable` | `>=3.12,<3.15` | +| `mlops` | Prefect (`prefect`) | `stable` | `>=3.12,<3.15` | +| `mlops` | Dagster (`dagster`) | `stable` | `>=3.12,<3.15` | +| `mlops` | Temporal (`temporal`) | `stable` | `>=3.12,<3.15` | +| `mlops` | Celery (`celery`) | `stable` | `>=3.12,<3.15` | +| `mlops` | DVC (`dvc`) | `stable` | `>=3.12,<3.15` | +| `mlops` | Feast (`feast`) | `stable` | `>=3.12,<3.15` | +| `mlops` | Evidently (`evidently`) | `stable` | `>=3.12,<3.15` | +| `mlops` | Polars (`polars`) | `stable` | `>=3.12,<3.15` | +| `mlops` | Pandera (`pandera`) | `stable` | `>=3.12,<3.15` | +| `quality` | DeepEval (`deepeval`) | `stable` | `>=3.12,<3.15` | +| `quality` | Ragas (`ragas`) | `stable` | `>=3.12,<3.15` | +| `quality` | Pydantic Evals (`pydantic-evals`) | `stable` | `>=3.12,<3.15` | +| `quality` | OpenTelemetry (`opentelemetry`) | `stable` | `>=3.12,<3.15` | +| `quality` | Langfuse (`langfuse`) | `platform` | `>=3.12,<3.15` | +| `quality` | Phoenix (`phoenix`) | `stable` | `>=3.12,<3.15` | +| `quality` | MLflow (`mlflow`) | `stable` | `>=3.12,<3.15` | +| `quality` | LangSmith (`langsmith`) | `platform` | `>=3.12,<3.15` | +| `quality` | Weights & Biases (`wandb`) | `platform` | `>=3.12,<3.15` | +| `deploy` | Docker / Compose (`docker`) | `stable` | `>=3.12,<3.15` | +| `deploy` | Render (`render`) | `platform` | `>=3.12,<3.15` | +| `deploy` | Fly.io (`fly`) | `platform` | `>=3.12,<3.15` | +| `deploy` | Vercel (`vercel`) | `platform` | `>=3.12,<3.15` | +| `deploy` | Railway (`railway`) | `platform` | `>=3.12,<3.15` | +| `deploy` | Hugging Face Spaces (`hf-spaces`) | `platform` | `>=3.12,<3.15` | +| `deploy` | Modal (`modal`) | `platform` | `>=3.12,<3.15` | +| `deploy` | RunPod (`runpod`) | `platform` | `>=3.12,<3.15` | +| `deploy` | BentoCloud (`bentocloud`) | `platform` | `>=3.12,<3.15` | +| `deploy` | AWS ECS (`aws-ecs`) | `platform` | `>=3.12,<3.15` | +| `deploy` | AWS SageMaker (`aws-sagemaker`) | `platform` | `>=3.12,<3.15` | +| `deploy` | Google Cloud Run (`cloud-run`) | `platform` | `>=3.12,<3.15` | +| `deploy` | Vertex AI (`vertex-ai`) | `platform` | `>=3.12,<3.15` | +| `deploy` | Azure Container Apps (`azure-container-apps`) | `platform` | `>=3.12,<3.15` | +| `deploy` | Azure ML (`azure-ml`) | `platform` | `>=3.12,<3.15` | diff --git a/template/pyproject.toml.jinja b/template/pyproject.toml.jinja index 8025e09..5845982 100644 --- a/template/pyproject.toml.jinja +++ b/template/pyproject.toml.jinja @@ -14,7 +14,7 @@ classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Programming Language :: Python :: 3", -{%- for v in ["3.11", "3.12", "3.13", "3.14"] %} +{%- for v in ["3.12", "3.13", "3.14"] %} {%- if v.split('.') | map('int') | list >= python_version.split('.') | map('int') | list %} "Programming Language :: Python :: {{ v }}", {%- endif %} diff --git a/template/src/{{ module_name }}/{% if workload in ['training', 'hybrid'] %}training.py{% endif %}.jinja b/template/src/{{ module_name }}/{% if workload in ['training', 'hybrid'] %}training.py{% endif %}.jinja index 68bced7..8e1fe74 100644 --- a/template/src/{{ module_name }}/{% if workload in ['training', 'hybrid'] %}training.py{% endif %}.jinja +++ b/template/src/{{ module_name }}/{% if workload in ['training', 'hybrid'] %}training.py{% endif %}.jinja @@ -45,7 +45,7 @@ def installed_training_tools() -> tuple[Any, ...]: def train(values: list[float]) -> dict[str, float]: - """Run a deterministic local training placeholder without downloading models.""" + """Run a deterministic local smoke step without downloading model artifacts.""" installed_training_tools() mean = sum(values) / len(values) if values else 0.0 return {"examples": float(len(values)), "mean": mean} diff --git a/tests/test_catalog.py b/tests/test_catalog.py index dbdf896..3aaefed 100644 --- a/tests/test_catalog.py +++ b/tests/test_catalog.py @@ -33,6 +33,58 @@ def test_catalog_and_public_artifact_match() -> None: assert len(generated["presets"]) == 12 +def test_python_312_is_the_global_minimum() -> None: + source = yaml.safe_load((REPO / "catalog" / "components.yml").read_text()) + config = yaml.safe_load((REPO / "copier.yml").read_text()) + + assert config["python_version"]["choices"] == ["3.12", "3.13", "3.14"] + for component in source["components"]: + assert component["python"].startswith(">=3.12,"), component["id"] + + +def test_every_copier_component_choice_exists_in_the_catalog() -> None: + source = yaml.safe_load((REPO / "catalog" / "components.yml").read_text()) + component_ids = {component["id"] for component in source["components"]} + config = yaml.safe_load((REPO / "copier.yml").read_text()) + choice_questions = ( + "workload", + "framework", + "interfaces", + "model_provider", + "embedding_provider", + "sql_store", + "document_store", + "vector_store", + "graph_store", + "cache_store", + "sql_abstraction", + "auth", + "serving", + "training_extensions", + "mlops_tools", + "quality_tools", + "deploy_target", + ) + + for question in choice_questions: + selected = set(config[question]["choices"].values()) - {"none"} + assert selected <= component_ids, (question, selected - component_ids) + + +def test_data_choices_match_their_catalog_roles() -> None: + source = yaml.safe_load((REPO / "catalog" / "components.yml").read_text()) + config = yaml.safe_load((REPO / "copier.yml").read_text()) + + for role in ("sql", "document", "vector", "graph", "cache"): + catalog_ids = { + component["id"] + for component in source["components"] + if role in component.get("roles", []) + } + question_ids = set(config[f"{role}_store"]["choices"].values()) - {"none"} + assert question_ids == catalog_ids, role + + def test_deliberately_excluded_projects_stay_excluded() -> None: text = (REPO / "catalog" / "components.yml").read_text().lower() for excluded in ("autogoal", "odmantic", "fastui", "reflex"): diff --git a/tests/test_generation.py b/tests/test_generation.py index 9025d86..5bf97ff 100644 --- a/tests/test_generation.py +++ b/tests/test_generation.py @@ -238,8 +238,7 @@ def test_python_version_drives_the_ci_matrix(copie) -> None: def test_eol_python_versions_are_not_offered(copie) -> None: """Versions at or near end of life must not be selectable. - Python 3.10 reaches EOL on 2026-10-31. Offering it would generate projects - that start life on an unsupported runtime. + v0.5 intentionally starts at 3.12, and older versions must not return. """ import yaml @@ -250,6 +249,7 @@ def test_eol_python_versions_are_not_offered(copie) -> None: assert "3.10" not in choices assert "3.9" not in choices + assert "3.11" not in choices assert config["python_version"]["default"] in choices diff --git a/tests/test_toolchain.py b/tests/test_toolchain.py index 53be8ca..7950bb1 100644 --- a/tests/test_toolchain.py +++ b/tests/test_toolchain.py @@ -14,6 +14,26 @@ SIMPLE_WORKLOADS = ["library", "cli", "api"] +@pytest.mark.slow +def test_minimum_python_312_project_runs(copie, uv: str) -> None: + """The declared v0.5 baseline must work, not merely appear in metadata.""" + project = copie.copy( + extra_answers=answers(preset="python-library", python_version="3.12") + ).project_dir + + assert_ok( + run([uv, "sync", "--python", "3.12", "--all-groups"], project), + "uv sync on Python 3.12", + ) + version = run( + [uv, "run", "python", "-c", "import sys; print(sys.version_info[:2])"], + project, + ) + assert_ok(version, "Python 3.12 runtime") + assert "(3, 12)" in version.stdout + assert_ok(run([uv, "run", "pytest", "-q"], project), "pytest on Python 3.12") + + @pytest.mark.slow @pytest.mark.parametrize("workload", SIMPLE_WORKLOADS) def test_generated_project_passes_its_own_checks(copie, uv: str, workload: str) -> None: From 8dae3e5849b1478d3c5ab59eb41a15960a9bd218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leynier=20Guti=C3=A9rrez=20Gonz=C3=A1lez?= Date: Sat, 8 Aug 2026 18:44:36 -0600 Subject: [PATCH 2/2] test: pin the Python 3.12 runtime in CI --- tests/test_toolchain.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/test_toolchain.py b/tests/test_toolchain.py index 7950bb1..f38eeef 100644 --- a/tests/test_toolchain.py +++ b/tests/test_toolchain.py @@ -26,12 +26,23 @@ def test_minimum_python_312_project_runs(copie, uv: str) -> None: "uv sync on Python 3.12", ) version = run( - [uv, "run", "python", "-c", "import sys; print(sys.version_info[:2])"], + [ + uv, + "run", + "--python", + "3.12", + "python", + "-c", + "import sys; print(sys.version_info[:2])", + ], project, ) assert_ok(version, "Python 3.12 runtime") assert "(3, 12)" in version.stdout - assert_ok(run([uv, "run", "pytest", "-q"], project), "pytest on Python 3.12") + assert_ok( + run([uv, "run", "--python", "3.12", "pytest", "-q"], project), + "pytest on Python 3.12", + ) @pytest.mark.slow