Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,44 @@ body:
required: true

- type: dropdown
id: project-type
id: workload
attributes:
label: Which project type did you generate?
options: [library, cli, api, not applicable]
label: Which workload did you generate?
options:
- library
- cli
- api
- web
- tui
- mcp
- agent
- rag
- inference
- training
- hybrid
- repository or documentation
validations:
required: true

- type: textarea
id: answers
attributes:
label: Contents of .copier-answers.yml
description: From the generated project. This tells us exactly how it was generated.
description: From the generated project, with secrets removed. This identifies every selected layer.
render: yaml

- type: input
id: version
attributes:
label: Template version or commit
placeholder: v0.5.0 or a commit SHA
validations:
required: true

- type: textarea
id: logs
attributes:
label: Relevant output
render: shell
validations:
required: true
23 changes: 23 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@ name: Feature request
description: Suggest an idea for the template
labels: ["enhancement"]
body:
- type: dropdown
id: layer
attributes:
label: Which layer does this affect?
options:
- workload or simple project
- framework or agent runtime
- interface
- model or embedding provider
- data engine or authentication
- training, serving, MLOps, or quality
- deployment or IaC
- agent skill
- repository tooling or documentation
validations:
required: true

- type: textarea
id: problem
attributes:
Expand All @@ -21,3 +38,9 @@ body:
id: alternatives
attributes:
label: What alternatives have you considered?

- type: textarea
id: validation
attributes:
label: How could this be validated without credentials?
description: Describe an import, command, route, local fake, parsed artifact, or other representative test.
20 changes: 19 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,24 @@ jobs:
- name: Generate and test affected presets offline
run: uv run pytest -m preset -n auto --basetemp="${{ runner.temp }}/pytest-presets"

docs:
name: Repository documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
with:
persist-credentials: false

- uses: astral-sh/setup-uv@v9.0.0
with:
python-version: "3.13"
enable-cache: true

- run: uv sync --locked --only-group docs

- name: Build Zensical site
run: uv run --only-group docs zensical build --clean --strict

toolchain:
name: Generated project / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -131,7 +149,7 @@ jobs:
ci:
name: CI
runs-on: ubuntu-latest
needs: [lint, structure, presets, toolchain, zizmor]
needs: [lint, structure, presets, docs, toolchain, zizmor]
if: always()
steps:
- name: Verify every job succeeded
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ __pycache__/
# Testing
.pytest_cache/
.coverage
site/

# Tool caches
.ruff_cache/
Expand All @@ -17,6 +18,7 @@ __pycache__/
# Editors
.vscode/
.idea/
.vercel/

# OS
.DS_Store
Expand Down
102 changes: 62 additions & 40 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,82 @@
# Python Template
# Contributing to Python Template

## Contributions are highly appreciated
Contributions are welcome, from a focused bug report to a complete component
integration. The repository generates many possible projects, so changes must
keep the catalog, templates, and executable tests aligned.

### All contributors will be granted credit on the following list
## Report an issue

* Leynier Gutiérrez González ([@leynier](https://github.com/leynier))
Use the [issue forms](https://github.com/leynier/python-template/issues/new/choose).
For a generated-project bug, include the relevant `.copier-answers.yml`, the
command that failed, and its output. Remove credentials before posting.

You can help out by:
Security vulnerabilities belong in a private
[GitHub Security Advisory](https://github.com/leynier/python-template/security/advisories/new),
not a public issue.

* Reporting a bug
* Reviewing the code
* Submitting a fix
* Proposing new features
* Becoming a maintainer
## Propose a component

## Branches
Explain:

We're using the following branches to manage work:
- which architectural layer and workload it serves;
- how it differs from supported components in that role;
- its maintained Python versions and upstream stability;
- what functional source and configuration the template should generate; and
- how CI can validate it without paid credentials.

* `develop` is semi-stable and should be used as the branch to fork from
* `main` is stable and ready for prod (or it will be once we merge in the first release)
* `feature`, `bug` branches: unstable development
The project intentionally excludes ODMantic, AutoGOAL, archived FastUI, and
archived Reflex. A new proposal should meet the inclusion criteria in the
[support model](docs/concepts/support.md).

## How to report bugs
## Develop a change

We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/leynier/python-template/issues/new/choose); it's that easy!
Create a focused branch from `main` and install every repository group:

### Write bug reports with detail, background, and sample code
```bash
git switch main
git pull --ff-only
git switch -c feat/short-description
uv sync --all-groups
```

**Great Bug Reports** tend to have:
For a catalog change, edit `catalog/components.yml` or `catalog/presets.yml`,
then compile deterministic outputs:

* A quick summary and/or background
* Steps to reproduce
* Be specific!
* Give sample code if you can.
* What you expected to happen
* What actually happens
* Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
```bash
uv run python scripts/compile_catalog.py
uv run python scripts/compile_catalog.py --check
```

We <3 thorough bug reports.
Do not edit `catalog/generated/`, `docs/reference/`, or
`template/_catalog_dependencies.jinja` by hand. Add functional source,
dependency, configuration, documentation, and tests for the selected component.

## How to contribute code
## Validate before opening a PR

We use GitHub to host code, to track issues and feature requests, as well as accept pull requests.
```bash
uv run python scripts/compile_catalog.py --check
uv run ruff check .
uv run ruff format --check .
uv run pytest -n auto
uv run --group docs zensical build --clean --strict
npx skills add . --list
```

Pull requests are the best way to propose changes to the codebase. We use a loose version of Git Flow
and actively welcome your pull requests:
Generate and exercise at least one representative project. A test that only
checks file presence is not enough when an import, CLI command, endpoint, tool,
training step, or container health route can be validated locally.

1. Create a new branch based on `develop`:
* Feature branches should start with `feature/`
* Bugfix branches should start with `bug/`
2. Implement your changes.
3. Add tests if applicable.
4. Make sure your code lints.
5. Issue that pull request!
Hosted CI repeats generated-project checks on Linux, macOS, and Windows. Keep
conditional source paths short enough for Windows temporary directories.

### Any contributions you make will be under the MIT License
## Pull requests

When you submit code changes, your submissions are understood to be under the same [MIT](LICENSE) that covers the project.
Keep each PR centered on one layer or cohesive outcome. Describe the supported
combination, commands run, external checks that were unavailable, and any
credential-gated behavior that remains operationally unverified. By submitting
a contribution, you agree that it is licensed under this repository's
[MIT license](LICENSE).

## Contributors

- Leynier Gutiérrez González ([@leynier](https://github.com/leynier))
46 changes: 46 additions & 0 deletions docs/concepts/layers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Composable layers

The generator treats architecture as a set of roles with compatibility rules.
This avoids the combinatorial maintenance cost of keeping a separate template
for every framework/provider/database/deploy permutation.

| Layer | Responsibility | Cardinality |
| --- | --- | --- |
| Workload | Primary shape and entry point | exactly one |
| Framework | Runtime or AI orchestration framework | zero or one |
| Interface | API, web, notebook, or terminal front end | zero or more |
| Model provider | Generative model access | zero or one |
| Embedding provider | Embedding model access | zero or one, independent |
| Data roles | SQL, document, vector, graph, cache | zero or one per role |
| SQL abstraction | SQLModel or SQLAlchemy | zero or one for eligible SQL stores |
| Auth | Request authentication | zero or one |
| Training extensions | Data, acceleration, tuning, optimization | zero or more |
| Serving | Model or gateway runtime | zero or one |
| MLOps and quality | Orchestration, evaluation, telemetry | zero or more |
| Deploy | Runtime destination | zero or one |
| IaC | Cloud resource definition | none, Pulumi, or Terraform |

## Compatibility is resolved before rendering

Copier validators reject combinations that cannot form a meaningful project.
Examples include using an agent framework for a plain library preset, adding a
SQL abstraction without a compatible SQL engine, or selecting IaC for a target
without a generated infrastructure contract.

Python compatibility is also visible in the catalog. The general baseline is
Python 3.12 or newer; components whose upstream support is narrower constrain
the available versions.

## Data roles stay explicit

A single engine can fill several roles when it supports them. Beaver, for
example, can cover document, vector, graph, and cache in a local-first stack.
That does not collapse the roles: each answer remains explicit, so a project can
later move only vector retrieval to a hosted engine without changing its graph
store.

## Portable deployment remains the base

Selecting a deploy target creates its native configuration and keeps a Docker
path. Cloud-specific Pulumi or Terraform is additive. Application code does not
become dependent on the IaC choice.
31 changes: 31 additions & 0 deletions docs/concepts/support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Support model

Every catalog component has a support tier and a Python compatibility range.
The tier describes what this repository can verify; it is not a judgment about
the upstream project's general quality.

## Stable

The integration can be exercised locally or offline without a paid account.
Generated dependencies, imports, configuration, and representative behavior are
covered by the test suite.

## Platform

The integration depends on a hosted API or cloud account. The repository tests
the generated client boundary, configuration, parsability, and local contract.
Users still need to supply credentials, accept provider costs, and perform a
real deployment verification.

## Experimental

The upstream API or the integration surface is evolving. It remains useful, but
may support fewer combinations and carries a narrower compatibility promise.

## Inclusion criteria

A component should add a distinct architectural role, have active maintenance,
support the template's Python baseline, and permit a meaningful automated test.
ODMantic, AutoGOAL, archived FastUI, and archived Reflex are intentionally not
included. New proposals should explain which layer they add and how a generated
project can validate the integration without embedding credentials.
56 changes: 56 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Getting started

## Requirements

Install [`uv`](https://docs.astral.sh/uv). Copier itself can run ephemerally
through `uvx`, so no global Python environment is required.

## Generate interactively

```bash
uvx copier copy --trust gh:leynier/python-template my-project
```

`--trust` allows the template's post-copy tasks to initialize Git and run
`uv sync`. The prompts first offer an editable preset, then expose the layers
and normal project metadata.

## Start from a preset

Preselect a recipe and keep the remaining answers interactive:

```bash
uvx copier copy --trust \
-d preset=pydantic-ai-openai \
gh:leynier/python-template my-agent
```

Use `-d key=value` repeatedly for automation. Keep the answer set in version
control through the generated `.copier-answers.yml` rather than maintaining a
second undocumented configuration.

## Verify the result

```bash
cd my-project
uv sync --all-groups
uv run ruff check .
uv run ruff format --check .
uv run pytest
```

The generated `readme.md` documents its primary entry point, environment
variables, Docker command, deployment adapter, and release flow when enabled.

## Pull in later template releases

Commit or stash local work before updating, then run:

```bash
uvx copier update
uv sync --all-groups
uv run pytest
```

Copier performs a three-way update using `.copier-answers.yml`; review the diff
because template changes and project-specific edits can touch the same file.
Loading
Loading