zenit 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zenit-1.0.0/LICENSE +21 -0
- zenit-1.0.0/MANIFEST.in +2 -0
- zenit-1.0.0/PKG-INFO +419 -0
- zenit-1.0.0/README.md +372 -0
- zenit-1.0.0/pyproject.toml +75 -0
- zenit-1.0.0/setup.cfg +4 -0
- zenit-1.0.0/src/scaffolder/__init__.py +0 -0
- zenit-1.0.0/src/scaffolder/addons/__pycache__/_registry.cpython-314.pyc +0 -0
- zenit-1.0.0/src/scaffolder/addons/_registry.py +30 -0
- zenit-1.0.0/src/scaffolder/addons/celery/__pycache__/addon.cpython-314.pyc +0 -0
- zenit-1.0.0/src/scaffolder/addons/celery/addon.py +68 -0
- zenit-1.0.0/src/scaffolder/addons/celery/files/tasks/celery_app.py.j2 +37 -0
- zenit-1.0.0/src/scaffolder/addons/celery/files/tasks/example_tasks.py.j2 +15 -0
- zenit-1.0.0/src/scaffolder/addons/docker/__pycache__/addon.cpython-314.pyc +0 -0
- zenit-1.0.0/src/scaffolder/addons/docker/addon.py +31 -0
- zenit-1.0.0/src/scaffolder/addons/docker/files/.dockerignore +14 -0
- zenit-1.0.0/src/scaffolder/addons/docker/files/Dockerfile.j2 +34 -0
- zenit-1.0.0/src/scaffolder/addons/docker/files/compose.yml.j2 +26 -0
- zenit-1.0.0/src/scaffolder/addons/github-actions/__pycache__/addon.cpython-314.pyc +0 -0
- zenit-1.0.0/src/scaffolder/addons/github-actions/addon.py +18 -0
- zenit-1.0.0/src/scaffolder/addons/github-actions/files/ci.yml.j2 +83 -0
- zenit-1.0.0/src/scaffolder/addons/redis/__pycache__/addon.cpython-314.pyc +0 -0
- zenit-1.0.0/src/scaffolder/addons/redis/addon.py +61 -0
- zenit-1.0.0/src/scaffolder/addons/redis/files/compose.redis.yml.j2 +11 -0
- zenit-1.0.0/src/scaffolder/addons/redis/files/redis.py +48 -0
- zenit-1.0.0/src/scaffolder/addons/sentry/__pycache__/addon.cpython-314.pyc +0 -0
- zenit-1.0.0/src/scaffolder/addons/sentry/addon.py +41 -0
- zenit-1.0.0/src/scaffolder/addons/sentry/files/sentry.py.j2 +35 -0
- zenit-1.0.0/src/scaffolder/assembler.py +266 -0
- zenit-1.0.0/src/scaffolder/context.py +85 -0
- zenit-1.0.0/src/scaffolder/dryrun.py +159 -0
- zenit-1.0.0/src/scaffolder/exceptions.py +2 -0
- zenit-1.0.0/src/scaffolder/generate/justfile.j2 +30 -0
- zenit-1.0.0/src/scaffolder/generate/pyproject.toml.j2 +58 -0
- zenit-1.0.0/src/scaffolder/generate.py +86 -0
- zenit-1.0.0/src/scaffolder/git.py +25 -0
- zenit-1.0.0/src/scaffolder/main.py +209 -0
- zenit-1.0.0/src/scaffolder/prompt.py +384 -0
- zenit-1.0.0/src/scaffolder/render.py +47 -0
- zenit-1.0.0/src/scaffolder/rollback.py +35 -0
- zenit-1.0.0/src/scaffolder/schema.py +118 -0
- zenit-1.0.0/src/scaffolder/templates/__pycache__/_load_config.cpython-314.pyc +0 -0
- zenit-1.0.0/src/scaffolder/templates/_common/__pycache__/apply.cpython-314.pyc +0 -0
- zenit-1.0.0/src/scaffolder/templates/_common/apply.py +42 -0
- zenit-1.0.0/src/scaffolder/templates/_common/envrc +4 -0
- zenit-1.0.0/src/scaffolder/templates/_common/gitattributes +13 -0
- zenit-1.0.0/src/scaffolder/templates/_common/gitignore +26 -0
- zenit-1.0.0/src/scaffolder/templates/_common/pre-commit-config.yaml +22 -0
- zenit-1.0.0/src/scaffolder/templates/_common/shell.nix +7 -0
- zenit-1.0.0/src/scaffolder/templates/_load_config.py +22 -0
- zenit-1.0.0/src/scaffolder/templates/blank/__pycache__/template.cpython-314.pyc +0 -0
- zenit-1.0.0/src/scaffolder/templates/blank/files/__main__.py +3 -0
- zenit-1.0.0/src/scaffolder/templates/blank/files/main.py.j2 +7 -0
- zenit-1.0.0/src/scaffolder/templates/blank/files/tests/test_main.py.j2 +9 -0
- zenit-1.0.0/src/scaffolder/templates/blank/template.py +51 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/__pycache__/template.cpython-314.pyc +0 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/.env.example +4 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/.env.j2 +4 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/alembic/env.py.j2 +50 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/alembic/script.py.mako +24 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/alembic.ini.j2 +33 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/api/router.py +12 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/api/routes/health.py +8 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/core/security.py +44 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/db/base.py +5 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/db/session.py +13 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/exceptions.py +25 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/lifecycle.py +14 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/main.py.j2 +7 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/models/mixins.py +27 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/schemas/common.py +14 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/scripts/wait_db.py +29 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/settings.py.j2 +20 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/tests/conftest.py.j2 +64 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/files/tests/test_health.py +7 -0
- zenit-1.0.0/src/scaffolder/templates/fastapi/template.py +172 -0
- zenit-1.0.0/src/scaffolder/ui.py +166 -0
- zenit-1.0.0/src/scaffolder/validate.py +85 -0
- zenit-1.0.0/src/zenit.egg-info/PKG-INFO +419 -0
- zenit-1.0.0/src/zenit.egg-info/SOURCES.txt +91 -0
- zenit-1.0.0/src/zenit.egg-info/dependency_links.txt +1 -0
- zenit-1.0.0/src/zenit.egg-info/entry_points.txt +3 -0
- zenit-1.0.0/src/zenit.egg-info/requires.txt +3 -0
- zenit-1.0.0/src/zenit.egg-info/top_level.txt +1 -0
- zenit-1.0.0/tests/test_apply_contributions.py +598 -0
- zenit-1.0.0/tests/test_assembler.py +251 -0
- zenit-1.0.0/tests/test_dryrun.py +277 -0
- zenit-1.0.0/tests/test_functional.py +334 -0
- zenit-1.0.0/tests/test_generate.py +194 -0
- zenit-1.0.0/tests/test_integration.py +392 -0
- zenit-1.0.0/tests/test_prompt.py +230 -0
- zenit-1.0.0/tests/test_render.py +164 -0
- zenit-1.0.0/tests/test_validate.py +116 -0
zenit-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Bojan Konjevic
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
zenit-1.0.0/MANIFEST.in
ADDED
zenit-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zenit
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Scaffold your next Python project with one command
|
|
5
|
+
Author-email: Bojan Konjevic <konjevicbojan1@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 Bojan Konjevic
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/BojanKonjevic/zenit
|
|
29
|
+
Project-URL: Repository, https://github.com/BojanKonjevic/zenit
|
|
30
|
+
Project-URL: Issues, https://github.com/BojanKonjevic/zenit/issues
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Programming Language :: Python :: 3
|
|
33
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
34
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
35
|
+
Classifier: Operating System :: OS Independent
|
|
36
|
+
Classifier: Development Status :: 4 - Beta
|
|
37
|
+
Classifier: Intended Audience :: Developers
|
|
38
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
39
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
40
|
+
Requires-Python: >=3.14
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: jinja2
|
|
44
|
+
Requires-Dist: typer>=0.12
|
|
45
|
+
Requires-Dist: pyyaml
|
|
46
|
+
Dynamic: license-file
|
|
47
|
+
|
|
48
|
+
# zenit
|
|
49
|
+
|
|
50
|
+
A CLI that scaffolds a new Python project from a template with optional addons — sets up the package structure, dev tooling, config files, and an initial git commit, then tells you what to run next.
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
zenit my-project
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## What it does
|
|
59
|
+
|
|
60
|
+
1. Asks you to pick a **template** (blank or FastAPI)
|
|
61
|
+
2. Asks you to pick **addons** (Docker, Redis, Celery, Sentry, GitHub Actions)
|
|
62
|
+
3. Generates the project directory, all files, `pyproject.toml`, and `justfile`
|
|
63
|
+
4. Runs `git init` and makes the first commit
|
|
64
|
+
|
|
65
|
+
It does not run `uv sync`, start servers, or do anything network-dependent. You get a directory you can immediately `cd` into and start working.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Requirements
|
|
70
|
+
|
|
71
|
+
All platforms need:
|
|
72
|
+
|
|
73
|
+
- **Python 3.14+**
|
|
74
|
+
- **uv 0.4+** — [install](https://docs.astral.sh/uv/getting-started/installation/)
|
|
75
|
+
- **git**
|
|
76
|
+
- **just** — [install](https://github.com/casey/just#installation) (optional but the generated projects use it heavily)
|
|
77
|
+
- **direnv** — optional, auto-activates the virtualenv on `cd` (see per-platform notes below)
|
|
78
|
+
|
|
79
|
+
The `fastapi` template additionally needs **Docker** running locally.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Installation
|
|
84
|
+
|
|
85
|
+
### macOS
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Install uv if you haven't
|
|
89
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
90
|
+
|
|
91
|
+
# Install zenit
|
|
92
|
+
uv tool install zenit
|
|
93
|
+
|
|
94
|
+
# Or run without installing
|
|
95
|
+
uvx zenit my-project
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**direnv** (recommended):
|
|
99
|
+
```bash
|
|
100
|
+
brew install direnv
|
|
101
|
+
# Add to ~/.zshrc or ~/.bash_profile:
|
|
102
|
+
eval "$(direnv hook zsh)" # or bash
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### Linux (non-NixOS)
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
111
|
+
uv tool install zenit
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**direnv**:
|
|
115
|
+
```bash
|
|
116
|
+
# Ubuntu/Debian
|
|
117
|
+
sudo apt install direnv
|
|
118
|
+
|
|
119
|
+
# Arch
|
|
120
|
+
sudo pacman -S direnv
|
|
121
|
+
|
|
122
|
+
# Fedora
|
|
123
|
+
sudo dnf install direnv
|
|
124
|
+
|
|
125
|
+
# Add to ~/.bashrc or ~/.zshrc:
|
|
126
|
+
eval "$(direnv hook bash)" # or zsh
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### NixOS
|
|
132
|
+
|
|
133
|
+
NixOS does not allow uv to download or manage its own Python binaries — `UV_PYTHON_DOWNLOADS` must be set to `never` and uv must use the system Python. zenit handles this for you when run via the Nix flake, but you need Python 3.14+ available in your environment first.
|
|
134
|
+
|
|
135
|
+
**Option A — run directly from the flake (recommended):**
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
nix run github:BojanKonjevic/zenit -- my-project
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
This uses the bundled flake which sets `UV_PYTHON_DOWNLOADS=never` and points uv at the Nix-provided Python 3.14 automatically.
|
|
142
|
+
|
|
143
|
+
**Option B — install and run manually:**
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Make sure python3.14 is in your PATH (via nix-shell, home-manager, etc.)
|
|
147
|
+
# Then:
|
|
148
|
+
UV_PYTHON_DOWNLOADS=never uv tool install zenit
|
|
149
|
+
UV_PYTHON_DOWNLOADS=never zenit my-project
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Generated projects on NixOS:**
|
|
153
|
+
|
|
154
|
+
When zenit detects it's running on NixOS (by checking `/etc/NIXOS`), it generates a `.envrc` that uses `use nix shell.nix` instead of uv's own environment management, and writes a `shell.nix` that provides the correct `LD_LIBRARY_PATH` for compiled wheels like greenlet. So the generated project will also work correctly on NixOS.
|
|
155
|
+
|
|
156
|
+
**direnv on NixOS** — add to your `configuration.nix`:
|
|
157
|
+
```nix
|
|
158
|
+
programs.direnv.enable = true;
|
|
159
|
+
```
|
|
160
|
+
Or install it in your user environment:
|
|
161
|
+
```bash
|
|
162
|
+
nix-env -iA nixpkgs.direnv
|
|
163
|
+
# Add to ~/.bashrc or ~/.zshrc:
|
|
164
|
+
eval "$(direnv hook bash)"
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### Windows
|
|
170
|
+
|
|
171
|
+
Windows is supported. The generated `justfile` uses `cmd` as the shell, and all `just` recipes work without WSL.
|
|
172
|
+
|
|
173
|
+
```powershell
|
|
174
|
+
# Install uv
|
|
175
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
176
|
+
|
|
177
|
+
# Install zenit
|
|
178
|
+
uv tool install zenit
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**direnv on Windows** — direnv does not have an official Windows build. Your options:
|
|
182
|
+
|
|
183
|
+
1. **Skip it** — instead of auto-activation, run `uv sync` once after scaffolding, then `uv run <command>` (or just use `just`, which routes through `uv run` already).
|
|
184
|
+
2. **Use WSL2** — install direnv inside WSL2 as per the Linux instructions above.
|
|
185
|
+
3. **Use `scoop`** — a community-maintained build exists: `scoop install direnv` (not officially supported).
|
|
186
|
+
|
|
187
|
+
zenit will copy `.envrc` regardless, but will warn you if direnv is not found rather than failing.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Usage
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
zenit <project-name> scaffold a new project
|
|
195
|
+
zenit <project-name> --dry-run preview what would be created (nothing is written)
|
|
196
|
+
zenit list-templates show available templates
|
|
197
|
+
zenit list-addons show available addons
|
|
198
|
+
zenit --version
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The interactive prompt uses arrow keys and space to select. If stdin is not a tty (e.g. piped input or CI), it falls back to numbered selection.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Templates
|
|
206
|
+
|
|
207
|
+
### `blank`
|
|
208
|
+
|
|
209
|
+
A minimal Python package with dev tooling. Good for CLIs, scripts, and libraries.
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
my-project/
|
|
213
|
+
src/my_project/
|
|
214
|
+
__init__.py
|
|
215
|
+
main.py
|
|
216
|
+
__main__.py
|
|
217
|
+
tests/
|
|
218
|
+
test_main.py
|
|
219
|
+
pyproject.toml
|
|
220
|
+
justfile
|
|
221
|
+
.gitignore
|
|
222
|
+
.envrc
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Includes: pytest, ruff, mypy, pytest-cov, ipython.
|
|
226
|
+
|
|
227
|
+
### `fastapi`
|
|
228
|
+
|
|
229
|
+
A production-oriented FastAPI setup. **Requires the `docker` addon** (selected automatically).
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
my-project/
|
|
233
|
+
src/my_project/
|
|
234
|
+
main.py FastAPI app + lifespan
|
|
235
|
+
lifecycle.py startup/shutdown logic
|
|
236
|
+
settings.py pydantic-settings (reads from .env)
|
|
237
|
+
exceptions.py HTTP exception helpers
|
|
238
|
+
api/
|
|
239
|
+
router.py
|
|
240
|
+
routes/
|
|
241
|
+
health.py GET /health → {"status": "ok"}
|
|
242
|
+
core/
|
|
243
|
+
security.py JWT encode/decode, bcrypt hashing
|
|
244
|
+
db/
|
|
245
|
+
base.py SQLAlchemy DeclarativeBase
|
|
246
|
+
session.py async engine, session factory, get_session dep
|
|
247
|
+
models/
|
|
248
|
+
mixins.py TimestampMixin (created_at, updated_at)
|
|
249
|
+
schemas/
|
|
250
|
+
common.py PaginationParams, PaginatedResponse
|
|
251
|
+
alembic/
|
|
252
|
+
env.py async-compatible Alembic env
|
|
253
|
+
versions/
|
|
254
|
+
tests/
|
|
255
|
+
conftest.py session + anon_client + client fixtures
|
|
256
|
+
integration/
|
|
257
|
+
test_health.py
|
|
258
|
+
unit/
|
|
259
|
+
fixtures/
|
|
260
|
+
scripts/
|
|
261
|
+
wait_db.py waits for postgres container to be ready
|
|
262
|
+
.env auto-generated with a random SECRET_KEY
|
|
263
|
+
.env.example
|
|
264
|
+
alembic.ini
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Addons
|
|
270
|
+
|
|
271
|
+
Addons are selected interactively and can be mixed freely with either template, with a few constraints noted below.
|
|
272
|
+
|
|
273
|
+
### `docker`
|
|
274
|
+
|
|
275
|
+
Generates a multi-stage `Dockerfile` (uv-based, minimal final image), `compose.yml`, and `.dockerignore`.
|
|
276
|
+
|
|
277
|
+
- For `blank`: compose starts just the app container.
|
|
278
|
+
- For `fastapi`: compose also starts a `db` (postgres:16) service.
|
|
279
|
+
- Required by `fastapi` (auto-selected).
|
|
280
|
+
|
|
281
|
+
### `redis`
|
|
282
|
+
|
|
283
|
+
Adds `src/<pkg>/integrations/redis.py` — an async connection pool with a `get_redis` FastAPI dependency and a `close_redis` shutdown helper.
|
|
284
|
+
|
|
285
|
+
- If `docker` is also selected: appends a `redis:7-alpine` service to `compose.yml`.
|
|
286
|
+
- If `docker` is not selected: writes a standalone `compose.redis.yml`.
|
|
287
|
+
- For `fastapi`: also patches `settings.py` to add a `redis_url` field.
|
|
288
|
+
- Required by `celery`.
|
|
289
|
+
|
|
290
|
+
### `celery`
|
|
291
|
+
|
|
292
|
+
Adds `src/<pkg>/tasks/celery_app.py` (Celery app configured against Redis) and `tasks/example_tasks.py` with a trivial `add` task.
|
|
293
|
+
|
|
294
|
+
- Requires `redis`.
|
|
295
|
+
- If `docker` is selected: appends `celery-worker` and `celery-beat` services to `compose.yml`.
|
|
296
|
+
|
|
297
|
+
### `sentry`
|
|
298
|
+
|
|
299
|
+
Adds `src/<pkg>/integrations/sentry.py` with an `init_sentry()` function that no-ops when `SENTRY_DSN` is unset — safe to commit and run locally without a DSN.
|
|
300
|
+
|
|
301
|
+
- For `fastapi`: patches `lifecycle.py` to call `init_sentry()` on startup, and patches `settings.py` and `.env` to add `SENTRY_DSN` / `SENTRY_ENVIRONMENT`.
|
|
302
|
+
- For `blank`: patches `main.py` to call `init_sentry()` at startup.
|
|
303
|
+
|
|
304
|
+
### `github-actions`
|
|
305
|
+
|
|
306
|
+
Writes `.github/workflows/ci.yml` that runs lint (`ruff check`), format check (`ruff format --check`), type check (`mypy`), and tests (`pytest`) on push and pull requests.
|
|
307
|
+
|
|
308
|
+
- Spins up a `postgres:16` service automatically when the `fastapi` template is used.
|
|
309
|
+
- Spins up a `redis:7-alpine` service automatically when `redis` is selected.
|
|
310
|
+
- Runs migrations before tests when postgres is present.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Generated commands (`just`)
|
|
315
|
+
|
|
316
|
+
All generated projects come with a `justfile`. Run `just` with no arguments to list what's available.
|
|
317
|
+
|
|
318
|
+
| Command | What it does |
|
|
319
|
+
|---|---|
|
|
320
|
+
| `just test` | run pytest |
|
|
321
|
+
| `just cov` | pytest with coverage report |
|
|
322
|
+
| `just lint` | ruff check |
|
|
323
|
+
| `just fmt` | ruff format |
|
|
324
|
+
| `just fix` | ruff check --fix + ruff format |
|
|
325
|
+
| `just check` | mypy |
|
|
326
|
+
| `just run` | start the app (uvicorn --reload for fastapi, python -m for blank) |
|
|
327
|
+
|
|
328
|
+
**FastAPI only:**
|
|
329
|
+
|
|
330
|
+
| Command | What it does |
|
|
331
|
+
|---|---|
|
|
332
|
+
| `just migrate "message"` | generate an Alembic migration |
|
|
333
|
+
| `just upgrade` | apply all pending migrations |
|
|
334
|
+
| `just downgrade` | roll back one step |
|
|
335
|
+
| `just db-create` | start db container, create app + test databases, migrate |
|
|
336
|
+
| `just db-reset` | drop and recreate both databases |
|
|
337
|
+
| `just wait-db` | wait until postgres is accepting connections |
|
|
338
|
+
|
|
339
|
+
**Docker addon:**
|
|
340
|
+
|
|
341
|
+
| Command | What it does |
|
|
342
|
+
|---|---|
|
|
343
|
+
| `just docker-up` | docker compose up --build |
|
|
344
|
+
| `just docker-down` | docker compose down |
|
|
345
|
+
|
|
346
|
+
**Redis addon:**
|
|
347
|
+
|
|
348
|
+
| Command | What it does |
|
|
349
|
+
|---|---|
|
|
350
|
+
| `just redis-up` | start redis |
|
|
351
|
+
| `just redis-down` | stop redis |
|
|
352
|
+
| `just redis-cli` | open redis-cli |
|
|
353
|
+
|
|
354
|
+
**Celery addon:**
|
|
355
|
+
|
|
356
|
+
| Command | What it does |
|
|
357
|
+
|---|---|
|
|
358
|
+
| `just celery-up` | start worker + beat via compose |
|
|
359
|
+
| `just celery-down` | stop worker + beat |
|
|
360
|
+
| `just celery-flower` | open Flower monitoring UI on port 5555 |
|
|
361
|
+
| `just celery-logs` | tail worker logs |
|
|
362
|
+
|
|
363
|
+
**Sentry addon:**
|
|
364
|
+
|
|
365
|
+
| Command | What it does |
|
|
366
|
+
|---|---|
|
|
367
|
+
| `just sentry-check` | print sentry-sdk version |
|
|
368
|
+
| `just sentry-test` | print whether SENTRY_DSN is set |
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## Dry run
|
|
373
|
+
|
|
374
|
+
Pass `--dry-run` to preview everything that would happen without touching disk:
|
|
375
|
+
|
|
376
|
+
```
|
|
377
|
+
zenit my-project --dry-run
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Output shows every file that would be created or modified, every dependency that would be added to `pyproject.toml`, every `just` recipe, and every git command — then exits without writing anything.
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## Adding auth to a FastAPI project
|
|
385
|
+
|
|
386
|
+
The `fastapi` template lays out the security plumbing but stops short of generating auth routes (everyone's auth is different). When you're ready:
|
|
387
|
+
|
|
388
|
+
1. Define `User` and `RefreshToken` models in `models/` — import them in `models/__init__.py` so Alembic discovers them.
|
|
389
|
+
2. Add `core/dependencies.py` with a `get_current_user` dependency using `decode_access_token` from `core/security.py`.
|
|
390
|
+
3. Add `api/routes/auth.py` with register, login, and refresh endpoints.
|
|
391
|
+
4. Register it in `api/router.py`.
|
|
392
|
+
5. Uncomment the auth block in `tests/conftest.py` to enable the authenticated `client` fixture.
|
|
393
|
+
6. Run `just db-create && just migrate "add users" && just upgrade`.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## Running from source
|
|
398
|
+
|
|
399
|
+
If you want to hack on zenit itself:
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
git clone https://github.com/BojanKonjevic/zenit.git
|
|
403
|
+
cd zenit
|
|
404
|
+
uv sync
|
|
405
|
+
uv run python main.py my-project
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
On NixOS, enter the dev shell first:
|
|
409
|
+
```bash
|
|
410
|
+
nix develop
|
|
411
|
+
python main.py my-project
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## License
|
|
417
|
+
|
|
418
|
+
MIT — see [LICENSE](LICENSE).
|
|
419
|
+
|