diff --git a/.gemini/commands/templatize.toml b/.gemini/commands/templatize.toml new file mode 100644 index 0000000..4fe2537 --- /dev/null +++ b/.gemini/commands/templatize.toml @@ -0,0 +1,29 @@ +description = "Templatize a new Python repo" +prompt = """ +I want you to "templatize" a new Python repository (cloned from a GitHub repo template) by following these steps: + +1. Run the `templatize` script: + ```bash + ./templatize + ``` + This updates placeholders like `{{REPO_NAME}}`, so everything is configured with my username, repo name, email, etc. +2. Install the package, dev dependencies, and pre-commit hooks (see README). +3. Use `pip list` or `uv pip list` to very which package versions were installed, and pin them in `pyproject.toml` for consistency. Do not add any new packages to `pyproject.toml` -- just pin the ones that are already listed. +4. Delete: + - the "usage" section of the README on templatization + - the `./templatize` script + - the `Templatize` step in `.github/workflows/test.yaml` + - the "templatize" slash-command file at `.gemini/commands/templatize.toml` +5. Update the README to give a brief description of the project. If you are unable to infer the description based on the repo, please ask me for more details. +6. Commit and push the changes. + ```bash + # you'll need to re-activate the virtual environment here + source .venv/bin/activate + git add . + git commit -m "Templatize" + git push + ``` + Type checking, linting, and formatting will run automatically on commit. You may fix any issues and recommit as needed. + +Do not add any new files. Only modify or delete existing files. +""" \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index e1e6433..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,5 +0,0 @@ -# These are supported funding model platforms - -github: [fkodom] -custom: [fkodom.substack.com] -# patreon: # Replace with a single Patreon username diff --git a/.github/disabled-workflows/test-slow.yaml b/.github/disabled-workflows/test-slow.yaml deleted file mode 100644 index 97a1474..0000000 --- a/.github/disabled-workflows/test-slow.yaml +++ /dev/null @@ -1,43 +0,0 @@ -name: Test Slow - -on: - workflow_dispatch: {} - pull_request: - types: [opened] - -jobs: - test: - name: Test - runs-on: ubuntu-latest - continue-on-error: true - - strategy: - matrix: - python: ["3.10"] - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install uv - uses: astral-sh/setup-uv@v5 - with: - python-version: ${{ matrix.python }} - - - name: Templatize - # Templatize the repo before attempting to run tests. (Tests will fail - # otherwise, due to syntax errors.) - # NOTE: Check if the 'templatize' script exists, so that this doesn't - # immediately fail for repos that have already run the script. - run: | - if test -f "templatize"; then - ./templatize - fi - - - name: Install Package - run: | - uv pip install -e .[test] - - - name: Test - run: | - uv run pytest --slow --cov --cov-report term-missing --cov-fail-under 80 tests/ diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 2913a60..30c4522 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -12,7 +12,7 @@ jobs: strategy: matrix: - python: ["3.10", "3.11", "3.12"] + python: ["3.11", "3.12"] steps: - name: Checkout @@ -39,6 +39,7 @@ jobs: - name: Test run: | + uv run ruff format --check . uv run ruff check . + uv run ty check . uv run pytest --cov --cov-report term-missing --cov-fail-under 80 tests/ - uv run mypy diff --git a/.gitignore b/.gitignore index 13f98a2..d2d6df2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .vscode +uv.lock worktrees/ # Byte-compiled / optimized / DLL files diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2255b1a..612acfc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,16 +1,23 @@ repos: - repo: local hooks: - - id: black - name: black + - id: ruff-format + name: ruff format stages: [pre-commit] language: system - entry: black + entry: ruff format types: [python] - - id: ruff + - id: ruff-check name: ruff check stages: [pre-commit] language: system entry: ruff check types: [python] + + - id: ty-check + name: ty check + stages: [pre-commit] + language: system + entry: ty check + types: [python] diff --git a/README.md b/README.md index 95a4bac..1daa861 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,28 @@ # {{REPO_NAME}} -A simple template for Python projects, with CI/CD configured through GitHub Actions. Compatible with any virtual environment manager (e.g. `uv`, `venv`, `pyenv`, `poetry`, `conda`). +A simple template for Python projects, with CI/CD configured through GitHub Actions. ## Usage 1. Create a new repository, using this one as a template. -2. Run the `templatize` script: +2. Install and open [Gemini CLI](https://github.com/google-gemini/gemini-cli), then run the `/templatize` command: ```bash - ./templatize + gemini run /templatize ``` - This updates placeholders like `{{REPO_NAME}}`, so everything is configured with your username, repo name, email, etc. -3. Commit and push the changes. - ```bash - git add . - git commit -m "Templatize" - git push - ``` -4. (Probably) delete this section of the README. ## Install -```bash -pip install "{{REPO_NAME}} @ git+ssh://git@github.com/{{REPO_OWNER}}/{{REPO_NAME}}.git" +> **Note:** For simplicity, I assume you are using [uv](https://docs.astral.sh/uv/getting-started/installation/), but this project is compatible with any virtual environment or package manager (`pip`, `venv`, `poetry`, `pipenv`, `conda`). -# Install all dev dependencies (tests etc.) -pip install "{{REPO_NAME}}[test] @ git+ssh://git@github.com/{{REPO_OWNER}}/{{REPO_NAME}}.git" +```bash +# Create and activate a new virtual environment +uv venv --python 3.12 +source .venv/bin/activate -# Setup pre-commit hooks +# Install development dependencies and pre-commit hoooks +uv sync --all-extras pre-commit install ``` @@ -37,11 +31,9 @@ pre-commit install | Tool | Description | Runs on | | --- | --- | --- | -| [black](https://github.com/psf/black) | Code formatter | - `git commit` (through `pre-commit`)
- `git push`
- pull requests | | [ruff](https://github.com/astral-sh/ruff) | Code linter | - `git commit` (through `pre-commit`)
- `git push`
- pull requests | +| [ty](https://docs.astral.sh/ty/) | Static type checker | - `git commit`
- pull requests | | [pytest](https://github.com/pytest-dev/pytest) | Unit testing framework | - `git push`
- pull requests | -| [mypy](https://github.com/python/mypy) | Static type checker | - `git push`
- pull requests | -| [pre-commit](https://github.com/pre-commit/pre-commit) | Pre-commit hooks | - `git commit` | | [twine](https://github.com/pypa/twine) $\dagger$ | PyPI package uploader | - New release (`git tag`) | > $\dagger$ Requires enabling the `publish.yaml` workflow. To activate, move the file from `.github/disabled-workflows/publish.yaml.disabled` to `.github/workflows/publish.yaml`, and set a valid PyPI token as `PYPI_API_TOKEN` in the repo secrets. diff --git a/pyproject.toml b/pyproject.toml index c36ae85..ef44f6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ description = "{{REPO_NAME}}" license = {text = "MIT"} dynamic = ["version", "readme"] # NOTE: Must be in sync with [tool.setuptools.dynamic] below dependencies = [] -requires-python = ">=3.8" +requires-python = ">=3.11" classifiers = ["Programming Language :: Python :: 3"] [tool.setuptools.dynamic] @@ -24,12 +24,12 @@ exclude = ["tests"] # extra packages (e.g. pip install .[test]) [project.optional-dependencies] test = [ - "black", "mypy", "pre-commit", "pytest", "pytest-cov", "ruff", + "ty", ] diff --git a/tests/conftest.py b/tests/conftest.py index cf3859b..e69de29 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,21 +0,0 @@ -import pytest - - -def pytest_addoption(parser): - parser.addoption("--slow", action="store_true") - - -def pytest_configure(config): - config.addinivalue_line("markers", "slow: slow to run") - - -def pytest_collection_modifyitems(config, items): - run_slow = config.getoption("--slow") - skip_fast = pytest.mark.skip(reason="remove --slow option to run") - skip_slow = pytest.mark.skip(reason="need --slow option to run") - - for item in items: - if ("slow" in item.keywords) and (not run_slow): - item.add_marker(skip_slow) - if ("slow" not in item.keywords) and (run_slow): - item.add_marker(skip_fast)