nuv 0.1.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.
@@ -0,0 +1,65 @@
1
+ # Copilot Instructions
2
+
3
+ ## Project overview
4
+
5
+ `nuv` is a CLI tool that scaffolds opinionated uv-based Python projects. Running `nuv new <name>` creates a fully configured project with argparse, logging, 100% test coverage, ruff linting/formatting, and ty type checking — all green from commit zero.
6
+
7
+ ## Tech stack
8
+
9
+ - **Language:** Python 3.14+
10
+ - **Package manager:** [uv](https://docs.astral.sh/uv/)
11
+ - **Testing:** pytest with 100% branch coverage enforced (`pytest-cov`)
12
+ - **Linting/formatting:** [ruff](https://docs.astral.sh/ruff/)
13
+ - **Type checking:** [ty](https://github.com/astral-sh/ty)
14
+
15
+ ## Repository layout
16
+
17
+ ```
18
+ src/nuv/
19
+ _logging.py # LOG_FORMAT + configure(); single source of logging config
20
+ cli.py # argparse entry point; routes subcommands
21
+ commands/
22
+ new.py # logic for `nuv new`: validate, scaffold, uv sync
23
+ templates/
24
+ script/ # *.tpl files rendered via str.format()
25
+ tests/
26
+ test_new.py # unit tests (100% coverage required)
27
+ ```
28
+
29
+ ## Development commands
30
+
31
+ ```bash
32
+ # Install dev dependencies
33
+ uv sync
34
+
35
+ # Run all tests (with coverage)
36
+ uv run pytest
37
+
38
+ # Lint
39
+ uv run ruff check src/ tests/
40
+
41
+ # Format check
42
+ uv run ruff format --check src/ tests/
43
+
44
+ # Type check
45
+ uv run ty check src/
46
+ ```
47
+
48
+ ## Coding conventions
49
+
50
+ - All source lives under `src/nuv/`; tests live under `tests/`.
51
+ - 100% branch coverage is enforced — every new code path must have a corresponding test.
52
+ - Use `str.format()` (not f-strings or Jinja) for file templates stored in `src/nuv/templates/`; placeholders use `{name}` syntax, and literal `{`/`}` must be written as `{{`/`}}`.
53
+ - Public functions are typed with PEP 604 union syntax (`X | None`) and return types annotated.
54
+ - Errors are surfaced by raising `ValueError`, `RuntimeError`, or `FileNotFoundError` (for missing templates); the CLI entry point catches these, logs them at ERROR level, and returns exit code 1.
55
+ - Logging is configured once via `_logging.configure()` (defined in `src/nuv/_logging.py`). Each module uses `log = logging.getLogger(__name__)`. `cli.main()` calls `configure(args.log_level)` with a `--log-level` flag (default `WARNING`). Scaffolded projects include an identical `_logging.py` module so the pattern carries forward.
56
+ - Do not use `print()` for user-facing output — use `log.info()` for success messages and `log.error()` for errors.
57
+ - Do not introduce new runtime dependencies without updating `pyproject.toml` and `uv.lock`.
58
+ - Follow ruff lint rules: `E`, `F`, `I`, `UP`, `B`, `SIM`.
59
+
60
+ ## Adding a new archetype
61
+
62
+ 1. Create `src/nuv/templates/<archetype>/` with the required `.tpl` files (see `script/` as a reference).
63
+ 2. Add any new logic to `src/nuv/commands/`.
64
+ 3. Wire the archetype in `cli.py` if needed.
65
+ 4. Add tests to maintain 100% coverage.
@@ -0,0 +1,71 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v5
17
+ with:
18
+ python-version: "3.14"
19
+ enable-cache: true
20
+
21
+ - name: Sync dependencies
22
+ run: uv sync --frozen
23
+
24
+ - name: Lint
25
+ run: |
26
+ uv run --frozen ruff check src/ tests/
27
+ uv run --frozen ruff format --check src/ tests/
28
+
29
+ - name: Type check
30
+ run: uv run --frozen ty check src/
31
+
32
+ test:
33
+ runs-on: ubuntu-latest
34
+ strategy:
35
+ fail-fast: false
36
+ matrix:
37
+ python-version: ["3.11", "3.14"]
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+
41
+ - name: Install uv
42
+ uses: astral-sh/setup-uv@v5
43
+ with:
44
+ python-version: ${{ matrix.python-version }}
45
+ enable-cache: true
46
+
47
+ - name: Sync dependencies
48
+ run: uv sync --frozen
49
+
50
+ - name: Test
51
+ run: uv run --frozen pytest
52
+
53
+ - name: Integration smoke test
54
+ if: matrix.python-version == '3.14'
55
+ run: |
56
+ uv run --frozen nuv new smoke-test --at /tmp/smoke-test
57
+ cd /tmp/smoke-test && uv sync --frozen && uv run --frozen pytest
58
+
59
+ - name: Build wheel for distribution smoke tests
60
+ if: matrix.python-version == '3.14'
61
+ run: uv build
62
+
63
+ - name: Tool install smoke test from wheel
64
+ if: matrix.python-version == '3.14'
65
+ run: |
66
+ uv tool install --force-reinstall dist/*.whl
67
+ nuv --help
68
+
69
+ - name: uvx smoke test from wheel
70
+ if: matrix.python-version == '3.14'
71
+ run: uvx --from dist/*.whl nuv --help
@@ -0,0 +1,71 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Validate semver version and tag match
16
+ if: github.ref_type == 'tag'
17
+ run: |
18
+ python - <<'PY'
19
+ import os
20
+ import re
21
+ import tomllib
22
+ from pathlib import Path
23
+
24
+ version = tomllib.loads(Path("pyproject.toml").read_text())["project"]["version"]
25
+ if not re.fullmatch(r"\d+\.\d+\.\d+", version):
26
+ raise SystemExit(f"pyproject version must be semver X.Y.Z, got: {version}")
27
+
28
+ tag = os.environ["GITHUB_REF_NAME"]
29
+ if not tag.startswith("v"):
30
+ raise SystemExit(f"release tag must start with 'v', got: {tag}")
31
+
32
+ if tag[1:] != version:
33
+ raise SystemExit(f"tag {tag} does not match project version {version}")
34
+ PY
35
+
36
+ - name: Install uv
37
+ uses: astral-sh/setup-uv@v5
38
+ with:
39
+ python-version: "3.14"
40
+
41
+ - name: Build distributions
42
+ run: uv build
43
+
44
+ - name: Validate distributions
45
+ run: uvx twine check dist/*
46
+
47
+ - name: Upload artifacts
48
+ uses: actions/upload-artifact@v4
49
+ with:
50
+ name: dist
51
+ path: dist/*
52
+
53
+ publish:
54
+ needs: build
55
+ runs-on: ubuntu-latest
56
+ permissions:
57
+ actions: read
58
+ contents: read
59
+ id-token: write
60
+ environment:
61
+ name: pypi
62
+ url: https://pypi.org/p/nuv
63
+ steps:
64
+ - name: Download built artifacts
65
+ uses: actions/download-artifact@v4
66
+ with:
67
+ name: dist
68
+ path: dist
69
+
70
+ - name: Publish package distributions to PyPI
71
+ uses: pypa/gh-action-pypi-publish@release/v1