13 KiB
Python Framework & Configuration Audit
Your primary task is to audit this project's configuration and ensure it aligns with modern Python development best practices. You should either create new configuration files for a new project or intelligently modify existing ones to meet these standards.
Do not blindly replace files. Your goal is to enforce a consistent, modern, and efficient development environment. Always explain the changes you are making and why they align with the framework principles outlined below.
Initial Project Analysis
Before making any changes, gather project information:
-
Check if this is a Git repository and get remote URL:
git remote -v
Use this information to populate the
[project.urls]
section inpyproject.toml
. -
Examine existing project structure:
- Look for existing
pyproject.toml
,setup.py
,requirements.txt
, orpoetry.lock
- Check for existing source code to understand the project name and structure
- Look for existing tests to understand testing framework (pytest, unittest, etc.)
- Read
README.md
if it exists - this often contains the best description of what the project does and can inform thename
,description
, andclassifiers
inpyproject.toml
- Look for existing
-
Identify the project type:
- Is it a library (should be installable)?
- Is it an application (needs entry points)?
- Does it need containerisation?
Guiding Principles
Before looking at the specific files, understand the philosophy behind this framework:
- Speed & Efficiency: We prioritise fast dependency management, builds, and CI/CD pipelines.
Tools like
uv
and multi-stage Docker builds are central to this. - Consolidation: We use
pyproject.toml
as the single source of truth for project metadata, dependencies, and tool configuration (linting, formatting, etc.). - Clarity & Consistency: Code and configuration should be easy to read and maintain. Comments in configuration files should explain non-obvious choices.
- Automation: The CI/CD workflow automates quality assurance and should be reliable whilst providing fast feedback.
1. Project & Tooling Configuration (pyproject.toml
)
The pyproject.toml
file is the backbone of the project's structure.
Your Task:
- If no
pyproject.toml
exists, create one based on the template below. - If one exists, audit it. Ensure it uses
ruff
for both linting and formatting, configures project metadata under the[project]
table, and uses the[tool.uv]
section for dependency management. - Pay close attention to the
ruff
linting codes. The template contains comments explaining the currently selected ruleset. If the project's file has outdated or conflicting codes, update them and explain the change. - IMPORTANT: Replace placeholder values with actual project information gathered from your initial analysis.
[project]
# Replace with actual project name (use directory name if unclear)
name = "your-project-name"
version = "0.1.0"
# Replace with appropriate description based on project contents
description = "A brief description of what this project does."
readme = "README.md"
# Choose appropriate licence (MIT, Apache-2.0, GPL-3.0, etc.)
license = { text = "MIT" }
# Replace with actual author information
authors = [{ name = "Your Name", email = "your.email@example.com" }]
maintainers = [{ name = "Your Name", email = "your.email@example.com" }]
# Adjust Python version based on project requirements
requires-python = ">=3.11"
classifiers = [
"Development Status :: 3 - Alpha", # Or 4 - Beta, 5 - Production/Stable
"License :: OSI Approved :: MIT License", # Match your chosen licence
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
# Adjust dependencies based on actual project requirements
dependencies = [
# Example common dependencies - replace with actual needs:
# "fastapi>=0",
# "requests>=2",
# "pydantic>=2",
# "pytz>=2025",
"uvicorn[standard]>=0",
]
[project.urls]
# Replace with actual repository URL from `git remote -v`
Homepage = "https://github.com/username/repository-name"
# Add additional URLs as appropriate:
# "Bug Reports" = "https://github.com/username/repository-name/issues"
# "Source" = "https://github.com/username/repository-name"
# "Documentation" = "https://your-project-docs.readthedocs.io/"
[dependency-groups]
dev = ["ruff>=0", "uv>=0"]
[tool.uv]
package = true
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
# Only include if this is an application with CLI entry points
[project.scripts]
# Replace with actual script name and module path
your-cli-command = "your_package.__main__:main"
[tool.setuptools]
packages = { find = {} }
[tool.ruff]
cache-dir = "/tmp/.ruff_cache"
fix = true
line-length = 100
preview = true
show-fixes = false
# Adjust target version to match requires-python
target-version = "py311"
unsafe-fixes = true
[tool.ruff.format]
line-ending = "auto"
skip-magic-trailing-comma = false
[tool.ruff.lint]
fixable = ["ALL"]
ignore = [
"ANN401", # use of Any type
"BLE001", # blind Exception usage
"COM812", # missing trailing comma
"CPY", # flake8-copyright
"FBT", # boolean arguments
"PLR0912", # too many branches
"PLR0913", # too many arguments
"PLR0915", # too many statements
"PLR0917", # too many positional arguments
"PLR6301", # method could be static
"RUF029", # async methods that don't await
"S104", # binding to all interfaces
"S110", # passed exceptions
"TRY301", # raise inside try block
]
select = ["ALL"]
unfixable = [
"F841", # local variable assigned but never used
"RUF100", # unused noqa comments
"T201", # don't strip print statement
]
[tool.ruff.lint.isort]
combine-as-imports = true
required-imports = ["from __future__ import annotations"]
[tool.ruff.lint.pydocstyle]
convention = "google"
2. Development Environment Setup
Essential Commands for Project Setup:
-
Install
uv
(if not already installed):curl -LsSf https://astral.sh/uv/install.sh | sh
-
Initialise virtual environment and install dependencies:
uv sync --all-groups
3. Containerisation (Dockerfile
)
Create this file only if the project needs containerisation (web services, deployable applications).
Our containerisation strategy focuses on creating minimal, secure, and efficient runtime images.
Your Task:
- Audit or create a
Dockerfile
that follows a multi-stage build process. - The fundamental pattern is:
- A
build
stage, based on a full Python image, where dependencies are compiled usinguv
. - A final, minimal
runtime
stage (e.g.,python-slim
) where the virtual environment from thebuild
stage is copied over.
- A
- Ensure the
PATH
environment variable in the final stage is correctly prepended with the virtual environment'sbin
directory. This ensures thatpython
commands execute from within the virtual environment by default. - Replace project-specific details with actual project information.
# Build stage using uv with a frozen lockfile and dependency caching
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS uv
WORKDIR /app
# Enable bytecode compilation and copy mode
ENV UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy
# Install dependencies using the lockfile
COPY pyproject.toml uv.lock ./
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev --no-editable --no-install-project
# Install the project in a second layer
COPY . .
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev --no-editable
# Prepare runtime image
FROM python:3.13-slim-bookworm AS runtime
WORKDIR /app
# Install minimal system dependencies and create runtime user
# Adjust system packages based on your project's needs
RUN apt-get update && apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/* \
&& groupadd -g 1000 appuser \
&& useradd -u 1000 -g 1000 -m appuser
# Copy only the virtual environment from the build stage
COPY --from=uv /app/.venv /app/.venv
# Switch to non-root user
USER appuser
# Set environment variables for runtime
ENV PATH="/app/.venv/bin:$PATH" \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
# Replace with appropriate startup command for your application
ENTRYPOINT ["uvicorn", "your_package", "--host", "0.0.0.0", "--port", "80"]
# Add health check for web services
# HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD curl -f http://localhost:80/health || exit 1
4. Continuous Integration
The CI workflow automates our quality checks. The goal is fast, parallel execution.
For Forgejo (.forgejo/workflows/docker-build.yml
)
- Audit or create a CI file that defines jobs for linting, testing, and building.
- Ensure the jobs are configured to run in parallel where possible.
- The workflow should leverage caching mechanisms for dependencies to speed up subsequent runs.
- The "lint" stage should simply run
ruff check .
andruff format --check .
. - The "test" stage should run the project's test suite, likely using
pytest
.
name: Docker Build
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
REGISTRY: git.tomfos.tr # Replace with your registry URL
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Add uv to PATH
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Set up Python
run: uv python install
- name: Install dependencies
run: uv sync
- name: Run ruff check
run: uv run ruff check .
- name: Run ruff format
run: uv run ruff format --check .
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Add uv to PATH
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Set up Python
run: uv python install
- name: Install dependencies
run: uv sync
- name: Run tests
run: uv run pytest --cov
build-and-push:
name: Build and Push
runs-on: ubuntu-latest
needs: [lint, test]
if: github.event_name == 'push'
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: https://github.com/docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: https://github.com/docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ gitea.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Determine image metadata
id: meta
uses: https://github.com/docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ gitea.repository }}
tags: |
type=ref,event=branch
type=ref,event=branch,suffix=-{{sha}}
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: https://github.com/docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ gitea.repository }}:build-cache
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ gitea.repository }}:build-cache,mode=max
How to Apply These Instructions
For a New Project
- Gather Information: Run
git remote -v
to get repository URL, examine directory structure - Create Configuration: Use the templates above, replacing placeholders with actual project details
- Setup Environment: Run
uv sync
to create virtual environment and install dependencies - Announce: "Setting up the project with modern Python development framework"
For an Existing Project
- Audit Current Setup: Compare existing files against framework guidelines
- Preserve Valid Configuration: Don't discard project-specific settings that don't conflict
- Migrate Dependencies: If
requirements.txt
exists, migrate topyproject.toml
dependency groups - Update Tools: Ensure
ruff
is used for both linting and formatting - Explain Changes: Clearly list proposed changes and justification for each
Migration from Legacy Tools
- From
setup.py
: Move metadata to[project]
table inpyproject.toml
- From
requirements.txt
: Move todependencies
and[dependency-groups]
inpyproject.toml
- From
black
+flake8
/pylint
: Replace withruff
for unified linting and formatting - From
pip
: Migrate touv
for faster dependency management