diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index b56f8b43..70be46da 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,10 +1,14 @@
{
"name": "substrate",
- "image": "ghcr.io/astral-sh/uv:python3.10-bookworm",
+ "image": "ghcr.io/astral-sh/uv:python3.10-trixie",
"features": {
- "ghcr.io/devcontainers/features/docker-in-docker:2": {},
+ "ghcr.io/devcontainers/features/docker-in-docker:2": {
+ "moby": false
+ },
"ghcr.io/devcontainers-extra/features/devcontainers-cli:1": {},
- "ghcr.io/devcontainers-extra/features/starship:1": {}
+ "ghcr.io/devcontainers-extra/features/apt-get-packages:1": {
+ "packages": "starship"
+ }
},
"remoteEnv": {
"VIRTUAL_ENV": "/opt/venv",
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index d91ed5ae..3e58bd3b 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -12,7 +12,7 @@ jobs:
steps:
- name: Set up uv
- uses: astral-sh/setup-uv@v6
+ uses: astral-sh/setup-uv@v7
- name: Check PR title
run: |
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 2c49d533..0e50ff01 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -7,7 +7,7 @@ on:
pull_request:
jobs:
- test-copier:
+ test:
runs-on: ubuntu-latest
strategy:
@@ -17,16 +17,16 @@ jobs:
project-type: ["app", "package"]
typing: ["optional", "strict"]
- name: "Copier: Python ${{ matrix.python-version }} ${{ matrix.project-type }} with ${{ matrix.typing }} typing"
+ name: "Python ${{ matrix.python-version }} ${{ matrix.project-type }} with ${{ matrix.typing }} typing"
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
path: substrate
- name: Set up uv
- uses: astral-sh/setup-uv@v6
+ uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "**/uv.lock"
@@ -66,50 +66,3 @@ jobs:
with:
context: ./my-project/
target: app
-
- test-cookiecutter:
- runs-on: ubuntu-latest
-
- strategy:
- fail-fast: true
- matrix:
- python-version: ["3.10", "3.13"]
- project-type: ["app", "package"]
-
- name: "Cookiecutter: Python ${{ matrix.python-version }} ${{ matrix.project-type }}"
-
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- path: poetry-cookiecutter
-
- - name: Set up uv
- uses: astral-sh/setup-uv@v6
- with:
- enable-cache: true
- cache-dependency-glob: "**/uv.lock"
-
- - name: Scaffold Python project
- run: |
- uvx cruft create --no-input --extra-context '{"project_type": "${{ matrix.project-type }}", "project_name": "My Project", "python_version": "3.10", "__docker_image":"superlinear/python-gpu:$PYTHON_VERSION-cuda11.8", "with_fastapi_api": "1", "with_typer_cli": "1"}' ./poetry-cookiecutter/
- cd my-project
- git config --global init.defaultBranch main
- git init
- git checkout -b test
- git add .
-
- - name: Lint and test project
- uses: devcontainers/ci@v0.3
- with:
- subFolder: ./my-project/
- runCmd: |
- poe lint
- poe test
-
- - name: Build app Docker image
- if: ${{ matrix.project-type == 'app' }}
- uses: docker/build-push-action@v6
- with:
- context: ./my-project/
- target: app
diff --git a/README.md b/README.md
index e64a2e32..593075b7 100644
--- a/README.md
+++ b/README.md
@@ -68,43 +68,6 @@ If your project is on GitHub, your docs will be published automatically to GitHu
> [!TIP]
> Make sure to [configure the source of your project's GitHub Pages as GitHub Actions in your project settings](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow) to allow the GitHub Actions workflow to publish your docs.
-## 🍪 Migrating from Cookiecutter
-
-> [!IMPORTANT]
-> This project was formerly known as `Poetry Cookiecutter` and was based on [Poetry](https://github.com/python-poetry/poetry) and [Cookiecutter](https://github.com/cookiecutter/cookiecutter). We will continue to support the original Cookiecutter-based template side by side with the new Copier-based template. However, we do encourage users to upgrade to the new Copier-based template by following the instructions below.
-
-To migrate a project from Cookiecutter to Copier, follow these steps:
-
-1. In your project repository, run:
-
- ```sh
- # Create a new branch
- git checkout -b rescaffold
-
- # Remove unnecessary files
- rm -f .cruft.json poetry.lock
-
- # Rescaffold the project without changing src/ and tests/
- uvx copier copy --overwrite --exclude src/ --exclude tests/ gh:superlinear-ai/substrate .
- ```
-
-2. Review the changes to `pyproject.toml` and reinsert your project's dependencies.
-3. Review the changes to `README.md` and reinsert your project's documentation.
-4. Commit and push all changes with:
-
- ```sh
- # Stage all changes
- git add .
-
- # Commit the staged changes
- git commit -m "build: upgrade scaffolding"
-
- # Push the committed changes
- git push origin rescaffold
- ```
-
-5. Create a PR from your branch, review it, and merge it!
-
## Contributing
@@ -150,8 +113,8 @@ The following development environments are supported:
pre-commit install --install-hooks
```
-3. _VS Code Dev Container_: clone this repository, open it with VS Code, and run Ctrl/⌘ + ⇧ + P → _Dev Containers: Reopen in Container_.
-4. _PyCharm Dev Container_: clone this repository, open it with PyCharm, [create a Dev Container with Mount Sources](https://www.jetbrains.com/help/pycharm/start-dev-container-inside-ide.html), and [configure an existing Python interpreter](https://www.jetbrains.com/help/pycharm/configuring-python-interpreter.html#widget) at `/opt/venv/bin/python`.
+4. _VS Code Dev Container_: clone this repository, open it with VS Code, and run Ctrl/⌘ + ⇧ + P → _Dev Containers: Reopen in Container_.
+5. _PyCharm Dev Container_: clone this repository, open it with PyCharm, [create a Dev Container with Mount Sources](https://www.jetbrains.com/help/pycharm/start-dev-container-inside-ide.html), and [configure an existing Python interpreter](https://www.jetbrains.com/help/pycharm/configuring-python-interpreter.html#widget) at `/opt/venv/bin/python`.
diff --git a/cookiecutter.json b/cookiecutter.json
deleted file mode 100644
index f548f9a9..00000000
--- a/cookiecutter.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "project_type": [
- "package",
- "app"
- ],
- "project_name": "{% if cookiecutter.project_type == 'app' %}My App{% else %}My Package{% endif %}",
- "project_description": "A Python {{ cookiecutter.project_type }} that reticulates splines.",
- "project_url": "https://github.com/user/my-{{ cookiecutter.project_type }}",
- "author_name": "John Smith",
- "author_email": "john@example.com",
- "python_version": "{% if cookiecutter.project_type == 'app' %}3.12{% else %}3.10{% endif %}",
- "development_environment": [
- "simple",
- "strict"
- ],
- "with_conventional_commits": "{% if cookiecutter.development_environment == 'simple' %}0{% else %}1{% endif %}",
- "with_fastapi_api": "0",
- "with_typer_cli": "0",
- "continuous_integration": [
- "GitHub",
- "GitLab"
- ],
- "private_package_repository_name": "",
- "private_package_repository_url": "",
- "__docker_image": "python:$PYTHON_VERSION-slim",
- "__docstring_style": "NumPy",
- "__project_name_kebab_case": "{{ cookiecutter.project_name|slugify }}",
- "__project_name_snake_case": "{{ cookiecutter.project_name|slugify(separator='_') }}"
-}
\ No newline at end of file
diff --git a/copier.yml b/copier.yml
index 44d7c933..b1f92e8b 100644
--- a/copier.yml
+++ b/copier.yml
@@ -102,4 +102,3 @@ project_name_snake_case:
documentation_url:
when: false
default: "{% if ci == 'github' %}https://{{ project_url.rstrip('/').split('/')[-2] }}.github.io/{{ project_url.rstrip('/').split('/')[-1] }}{% else %}{{ project_url }}{% endif %}"
-
diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py
deleted file mode 100644
index 7523c3b5..00000000
--- a/hooks/post_gen_project.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import os
-import shutil
-
-# Read Cookiecutter configuration.
-project_name = "{{ cookiecutter.__project_name_snake_case }}"
-development_environment = "{{ cookiecutter.development_environment }}"
-with_conventional_commits = int("{{ cookiecutter.with_conventional_commits }}")
-with_fastapi_api = int("{{ cookiecutter.with_fastapi_api }}")
-with_typer_cli = int("{{ cookiecutter.with_typer_cli }}")
-continuous_integration = "{{ cookiecutter.continuous_integration }}"
-is_application = "{{ cookiecutter.project_type == 'app' }}" == "True"
-
-# Remove py.typed and Dependabot if not in strict mode.
-if development_environment != "strict":
- os.remove(f"src/{project_name}/py.typed")
- os.remove(".github/dependabot.yml")
-
-# Remove FastAPI if not selected.
-if not with_fastapi_api:
- os.remove(f"src/{project_name}/api.py")
- os.remove("tests/test_api.py")
-
-# Remove Typer if not selected.
-if not with_typer_cli:
- os.remove(f"src/{project_name}/cli.py")
- os.remove("tests/test_cli.py")
-
-# Remove the continuous integration provider that is not selected.
-if continuous_integration != "GitHub":
- shutil.rmtree(".github/")
-elif continuous_integration != "GitLab":
- os.remove(".gitlab-ci.yml")
-
-# Remove unused GitHub Actions workflows.
-if continuous_integration == "GitHub":
- if is_application:
- os.remove(".github/workflows/publish.yml")
- else:
- os.remove(".github/workflows/deploy.yml")
- if not with_conventional_commits:
- os.remove(".github/workflows/pr.yml")
diff --git a/template/.devcontainer/devcontainer.json.jinja b/template/.devcontainer/devcontainer.json.jinja
index aa0d9787..2def936b 100644
--- a/template/.devcontainer/devcontainer.json.jinja
+++ b/template/.devcontainer/devcontainer.json.jinja
@@ -5,9 +5,13 @@
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}/",
"features": {
{%- if project_type == 'app' %}
- "ghcr.io/devcontainers/features/docker-in-docker:2": {},
+ "ghcr.io/devcontainers/features/docker-in-docker:2": {
+ "moby": false
+ },
{%- endif %}
- "ghcr.io/devcontainers-extra/features/starship:1": {}
+ "ghcr.io/devcontainers-extra/features/apt-get-packages:1": {
+ "packages": "starship"
+ }
},
"overrideCommand": true,
"remoteUser": "user",
diff --git a/template/Dockerfile.jinja b/template/Dockerfile.jinja
index 946c9226..e1caecce 100644
--- a/template/Dockerfile.jinja
+++ b/template/Dockerfile.jinja
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1
-FROM ghcr.io/astral-sh/uv:python{{ python_version }}-bookworm AS dev
+FROM ghcr.io/astral-sh/uv:python{{ python_version }}-trixie AS dev
# Create and activate a virtual environment [1].
# [1] https://docs.astral.sh/uv/concepts/projects/config/#project-environment-path
diff --git a/template/{% if ci == 'github' %}.github{% endif %}/workflows/docs.yml.jinja b/template/{% if ci == 'github' %}.github{% endif %}/workflows/docs.yml.jinja
index 07e118c7..30dd10b3 100644
--- a/template/{% if ci == 'github' %}.github{% endif %}/workflows/docs.yml.jinja
+++ b/template/{% if ci == 'github' %}.github{% endif %}/workflows/docs.yml.jinja
@@ -26,7 +26,7 @@ jobs:
uses: actions/checkout@v5
- name: Install uv
- uses: astral-sh/setup-uv@v6
+ uses: astral-sh/setup-uv@v7
- name: Build docs
run: uv run mkdocs build
diff --git a/template/{% if ci == 'github' %}.github{% endif %}/workflows/test.yml.jinja b/template/{% if ci == 'github' %}.github{% endif %}/workflows/test.yml.jinja
index 1be58c15..e64fac25 100644
--- a/template/{% if ci == 'github' %}.github{% endif %}/workflows/test.yml.jinja
+++ b/template/{% if ci == 'github' %}.github{% endif %}/workflows/test.yml.jinja
@@ -23,7 +23,7 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Set up Node.js
uses: actions/setup-node@v4
diff --git a/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if project_type == 'app' %}deploy.yml{% endif %}.jinja b/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if project_type == 'app' %}deploy.yml{% endif %}.jinja
index 48a0200c..2b63fa97 100644
--- a/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if project_type == 'app' %}deploy.yml{% endif %}.jinja
+++ b/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if project_type == 'app' %}deploy.yml{% endif %}.jinja
@@ -30,7 +30,7 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Log in to the Docker registry
uses: docker/login-action@v3
diff --git a/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if project_type == 'package' %}publish.yml{% endif %}.jinja b/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if project_type == 'package' %}publish.yml{% endif %}.jinja
index c7c7859d..4431f14c 100644
--- a/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if project_type == 'package' %}publish.yml{% endif %}.jinja
+++ b/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if project_type == 'package' %}publish.yml{% endif %}.jinja
@@ -14,10 +14,10 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Install uv
- uses: astral-sh/setup-uv@v6
+ uses: astral-sh/setup-uv@v7
- name: Publish package
run: |
diff --git a/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if with_conventional_commits %}pr.yml{% endif %}.jinja b/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if with_conventional_commits %}pr.yml{% endif %}.jinja
index 119fe789..6905270b 100644
--- a/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if with_conventional_commits %}pr.yml{% endif %}.jinja
+++ b/template/{% if ci == 'github' %}.github{% endif %}/workflows/{% if with_conventional_commits %}pr.yml{% endif %}.jinja
@@ -12,7 +12,7 @@ jobs:
steps:
- name: Set up uv
- uses: astral-sh/setup-uv@v6
+ uses: astral-sh/setup-uv@v7
- name: Check PR title
run: |
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.devcontainer/devcontainer.json b/{{ cookiecutter.__project_name_kebab_case }}/.devcontainer/devcontainer.json
deleted file mode 100644
index a59cd5c8..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/.devcontainer/devcontainer.json
+++ /dev/null
@@ -1,85 +0,0 @@
-{
- "name": "{{ cookiecutter.__project_name_kebab_case }}",
- "dockerComposeFile": "../docker-compose.yml",
- "service": "devcontainer",
- "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}/",
- "remoteUser": "user",
- "overrideCommand": true,
- "postStartCommand": "cp --update /opt/build/poetry/poetry.lock /workspaces/${localWorkspaceFolderBasename}/ && mkdir -p /workspaces/${localWorkspaceFolderBasename}/.git/hooks/ && cp --update /opt/build/git/* /workspaces/${localWorkspaceFolderBasename}/.git/hooks/",
- "customizations": {
- "jetbrains": {
- "backend": "PyCharm",
- "plugins": [
- "com.github.copilot"
- ],
- "settings": {
- "org.jetbrains.plugins.terminal:app:TerminalOptionsProvider.myShellPath": "/usr/bin/zsh"
- }
- },
- "vscode": {
- "extensions": [
- "charliermarsh.ruff",
- "GitHub.copilot",
- "GitHub.copilot-chat",
- {%- if cookiecutter.continuous_integration == "GitHub" %}
- "GitHub.vscode-github-actions",
- "GitHub.vscode-pull-request-github",
- {%- elif cookiecutter.continuous_integration == "GitLab" %}
- "GitLab.gitlab-workflow",
- {%- endif %}
- "ms-azuretools.vscode-docker",
- "ms-python.mypy-type-checker",
- "ms-python.python",
- "ms-toolsai.jupyter",
- "ryanluker.vscode-coverage-gutters",
- "tamasfe.even-better-toml",
- "visualstudioexptteam.vscodeintellicode"
- ],
- "settings": {
- "coverage-gutters.coverageFileNames": [
- "reports/coverage.xml"
- ],
- "editor.codeActionsOnSave": {
- "source.fixAll": "explicit",
- "source.organizeImports": "explicit"
- },
- "editor.formatOnSave": true,
- "[python]": {
- "editor.defaultFormatter": "charliermarsh.ruff"
- },
- "[toml]": {
- "editor.formatOnSave": false
- },
- "editor.rulers": [
- 100
- ],
- "files.autoSave": "onFocusChange",
- "github.copilot.chat.agent.enabled": true,
- "github.copilot.chat.codesearch.enabled": true,
- "github.copilot.chat.edits.enabled": true,
- "github.copilot.nextEditSuggestions.enabled": true,
- "jupyter.kernels.excludePythonEnvironments": ["/usr/local/bin/python"],
- "mypy-type-checker.importStrategy": "fromEnvironment",
- "mypy-type-checker.preferDaemon": true,
- "notebook.codeActionsOnSave": {
- "notebook.source.fixAll": "explicit",
- "notebook.source.organizeImports": "explicit"
- },
- "notebook.formatOnSave.enabled": true,
- "python.defaultInterpreterPath": "/opt/{{ cookiecutter.__project_name_kebab_case }}-env/bin/python",
- "python.terminal.activateEnvironment": false,
- "python.testing.pytestEnabled": true,
- "ruff.importStrategy": "fromEnvironment",
- {%- if cookiecutter.development_environment == "strict" %}
- "ruff.logLevel": "warning",
- {%- endif %}
- "terminal.integrated.defaultProfile.linux": "zsh",
- "terminal.integrated.profiles.linux": {
- "zsh": {
- "path": "/usr/bin/zsh"
- }
- }
- }
- }
- }
-}
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.dockerignore b/{{ cookiecutter.__project_name_kebab_case }}/.dockerignore
deleted file mode 100644
index c17c79a6..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/.dockerignore
+++ /dev/null
@@ -1,5 +0,0 @@
-# Caches
-.*_cache/
-
-# Git
-.git/
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.github/dependabot.yml b/{{ cookiecutter.__project_name_kebab_case }}/.github/dependabot.yml
deleted file mode 100644
index b402007e..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/.github/dependabot.yml
+++ /dev/null
@@ -1,36 +0,0 @@
-version: 2
-
-updates:
- - package-ecosystem: github-actions
- directory: /
- schedule:
- interval: monthly
- commit-message:
- prefix: "ci"
- prefix-development: "ci"
- include: scope
- groups:
- ci-dependencies:
- patterns:
- - "*"
- - package-ecosystem: pip
- directory: /
- schedule:
- interval: monthly
- commit-message:
- prefix: "chore"
- prefix-development: "build"
- include: scope
- allow:
- {%- if cookiecutter.project_type == "app" %}
- - dependency-type: production
- {%- endif %}
- - dependency-type: development
- versioning-strategy: increase
- groups:
- {%- if cookiecutter.project_type == "app" %}
- runtime-dependencies:
- dependency-type: production
- {%- endif %}
- development-dependencies:
- dependency-type: development
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/deploy.yml b/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/deploy.yml
deleted file mode 100644
index 8771a41c..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/deploy.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-name: Deploy
-
-on:
- push:
- tags:
- - "v*.*.*"
- workflow_dispatch:
- inputs:
- environment:
- required: true
- description: Deployment environment
- default: development
- type: choice
- options:
- - feature
- - development
- - test
- - acceptance
- - production
-
-env:
- DEFAULT_DEPLOYMENT_ENVIRONMENT: feature
- DOCKER_REGISTRY: ghcr.io
-
-jobs:
- deploy:
- runs-on: ubuntu-latest
-
- if: startsWith(github.ref, 'refs/tags/v')
-
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Log in to the Docker registry
- uses: docker/login-action@v3
- with:
- registry: {% raw %}${{ env.DOCKER_REGISTRY }}{% endraw %}
- username: {% raw %}${{ github.actor }}{% endraw %}
- password: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %}
-
- - name: Set Docker image tag
- run: echo "GIT_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
-
- - name: Build and push Docker image
- uses: docker/build-push-action@v5
- with:
- context: .
- push: true
- {%- if cookiecutter.private_package_repository_name %}
- secrets: |
- "poetry_auth=[http-basic.{{ cookiecutter.private_package_repository_name|slugify }}]
- username = ""{% raw %}${{{% endraw %} secrets.POETRY_HTTP_BASIC_{{ cookiecutter.private_package_repository_name|slugify(separator="_")|upper }}_USERNAME }}""
- password = ""{% raw %}${{{% endraw %} secrets.POETRY_HTTP_BASIC_{{ cookiecutter.private_package_repository_name|slugify(separator="_")|upper }}_PASSWORD }}""
- "
- {%- endif %}
- tags: |
- {% raw %}${{ env.DOCKER_REGISTRY }}/${{ github.repository_owner }}/${{ github.repository }}:${{ github.event.inputs.environment || env.DEFAULT_DEPLOYMENT_ENVIRONMENT }}{% endraw %}
- {% raw %}${{ env.DOCKER_REGISTRY }}/${{ github.repository_owner }}/${{ github.repository }}:${{ env.GIT_TAG }}{% endraw %}
- target: app
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/pr.yml b/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/pr.yml
deleted file mode 100644
index 119fe789..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/pr.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-name: PR
-
-on:
- pull_request:
- types: [edited, opened, reopened, synchronize]
-
-jobs:
- title:
- runs-on: ubuntu-latest
-
- name: Check PR title
-
- steps:
- - name: Set up uv
- uses: astral-sh/setup-uv@v6
-
- - name: Check PR title
- run: |
- uvx --from=commitizen cz check --message "{% raw %}${{ github.event.pull_request.title }}{% endraw %}"
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/publish.yml b/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/publish.yml
deleted file mode 100644
index 503f9f6c..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/publish.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-name: Publish
-
-on:
- release:
- types:
- - created
-
-jobs:
- publish:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: "{{ cookiecutter.python_version }}"
-
- - name: Install Poetry
- run: pip install --no-input poetry
-
- - name: Publish package
- run: |
- {%- if cookiecutter.private_package_repository_name %}
- poetry config repositories.private "{{ cookiecutter.private_package_repository_url.replace('simple/', '').replace('simple', '') }}"
- poetry config http-basic.private "{% raw %}${{{% endraw %} secrets.POETRY_HTTP_BASIC_{{ cookiecutter.private_package_repository_name|slugify(separator="_")|upper }}_USERNAME }}" "{% raw %}${{{% endraw %} secrets.POETRY_HTTP_BASIC_{{ cookiecutter.private_package_repository_name|slugify(separator="_")|upper }}_PASSWORD }}"
- poetry publish --build --repository private
- {%- else %}
- poetry config pypi-token.pypi "{% raw %}${{ secrets.POETRY_PYPI_TOKEN_PYPI }}{% endraw %}"
- poetry publish --build
- {%- endif %}
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/test.yml b/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/test.yml
deleted file mode 100644
index ce94c5b8..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/test.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-name: Test
-
-on:
- push:
- branches:
- - main
- - master
- pull_request:
-
-jobs:
- test:
- runs-on: ubuntu-latest
-
- strategy:
- fail-fast: false
- matrix:
- python-version: ["{{ cookiecutter.python_version }}"]
-
- name: Python {% raw %}${{{% endraw %} matrix.python-version }}
-
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Set up Node.js
- uses: actions/setup-node@v4
- with:
- node-version: 23
-
- - name: Install @devcontainers/cli
- run: npm install --location=global @devcontainers/cli@0.76.0
-
- - name: Start Dev Container
- run: |
- git config --global init.defaultBranch main
- devcontainer up --workspace-folder .
- env:
- PYTHON_VERSION: {% raw %}${{{% endraw %} matrix.python-version }}
-
- - name: Lint {{ cookiecutter.project_type }}
- run: devcontainer exec --workspace-folder . poe lint
-
- - name: Test {{ cookiecutter.project_type }}
- run: devcontainer exec --workspace-folder . poe test
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.gitignore b/{{ cookiecutter.__project_name_kebab_case }}/.gitignore
deleted file mode 100644
index 2ef3a6b2..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/.gitignore
+++ /dev/null
@@ -1,68 +0,0 @@
-# Coverage.py
-htmlcov/
-reports/
-
-# cruft
-*.rej
-
-# Data
-*.csv*
-*.dat*
-*.pickle*
-*.xls*
-*.zip*
-data/
-
-# direnv
-.envrc
-
-# dotenv
-.env
-
-# Hypothesis
-.hypothesis/
-
-# Jupyter
-*.ipynb
-.ipynb_checkpoints/
-notebooks/
-
-# macOS
-.DS_Store
-
-# mise
-mise.local.toml
-
-# mypy
-.dmypy.json
-.mypy_cache/
-
-# Node.js
-node_modules/
-
-# Poetry
-.venv/
-dist/
-
-# PyCharm
-.idea/
-
-# pyenv
-.python-version
-
-# pytest
-.pytest_cache/
-
-# Python
-__pycache__/
-*.egg-info/
-*.py[cdo]
-
-# Ruff
-.ruff_cache/
-
-# Terraform
-.terraform/
-
-# VS Code
-.vscode/
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.gitlab-ci.yml b/{{ cookiecutter.__project_name_kebab_case }}/.gitlab-ci.yml
deleted file mode 100644
index 5264202a..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/.gitlab-ci.yml
+++ /dev/null
@@ -1,148 +0,0 @@
-stages:
- - build
- - test
- - {% if cookiecutter.project_type == "package" %}publish{% else %}deploy{% endif %}
-
-variables:
- DOCKER_TLS_CERTDIR: "/certs"
-
-.python_matrix:
- parallel:
- matrix:
- - PYTHON_VERSION: ["{{ cookiecutter.python_version }}"]
-
-.install_devcontainers_cli:
- cache:
- paths:
- - .apk_cache
- - .npm_cache
- before_script:
- - mkdir -p .apk_cache && apk add --cache-dir .apk_cache npm
- - npm install --cache .npm_cache --global --prefer-offline @devcontainers/cli@0.73.0
-
-# Build the Dev Container.
-Build:
- extends:
- - .python_matrix
- - .install_devcontainers_cli
- stage: build
- image: docker:latest
- services:
- - docker:dind
- script:
- - |
- # Log in to the Docker registry.
- echo "$CI_REGISTRY_PASSWORD" | docker login --username "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
-
- # Compute a hash for the Dev Container image.
- export CI_IMAGE_SHA="$(sha1sum Dockerfile poetry.lock pyproject.toml | sha1sum | cut -c 1-8)"
- echo "CI_IMAGE_SHA=$CI_IMAGE_SHA" >> .env
-
- # Build and push the Dev Container image, unless it already exists.
- IMAGE_NAME="$CI_REGISTRY_IMAGE/devcontainer:$PYTHON_VERSION-$CI_IMAGE_SHA"
- IMAGE_EXISTS=${IMAGE_EXISTS:-$(timeout 2s docker pull "$IMAGE_NAME" >/dev/null 2>&1 && echo $? || echo $?)}
- if [ "$IMAGE_EXISTS" -ne 1 ]; then
- echo "$IMAGE_NAME exists, skipping this job..."
- else
- {%- if cookiecutter.private_package_repository_name %}
- echo "[http-basic.{{ cookiecutter.private_package_repository_name|slugify }}]" >> auth.toml
- echo "username = \"gitlab-ci-token\"" >> auth.toml
- echo "password = \"$CI_JOB_TOKEN\"" >> auth.toml
- export $POETRY_AUTH_TOML_PATH=$(pwd)/auth.toml
- {%- endif %}
- devcontainer build --image-name "$IMAGE_NAME" --workspace-folder .
- docker push "$IMAGE_NAME"
- fi
- artifacts:
- reports:
- dotenv: .env
-
-# Lint and test the {{ cookiecutter.project_type }}.
-Test:
- extends:
- - .python_matrix
- - .install_devcontainers_cli
- stage: test
- image: docker:latest
- services:
- - docker:dind
- script:
- - |
- devcontainer up --cache-from "type=registry,ref=$CI_REGISTRY_IMAGE/devcontainer:$PYTHON_VERSION-$CI_IMAGE_SHA" --workspace-folder .
- devcontainer exec --workspace-folder . git config --global --add safe.directory /workspaces/{{ cookiecutter.__project_name_kebab_case }}
- devcontainer exec --workspace-folder . poe lint
- devcontainer exec --workspace-folder . poe test
- coverage: '/^TOTAL.*\s+(\d+(?:\.\d+)?)%/'
- artifacts:
- reports:
- coverage_report:
- coverage_format: cobertura
- path: reports/coverage.xml
- junit:
- - reports/mypy.xml
- - reports/pytest.xml
- untracked: true
- when: always
-
-{% if cookiecutter.project_type == "package" -%}
-# Publish this package version to {% if cookiecutter.private_package_repository_name %}a private package repository{% else %}PyPI{% endif %}.
-Publish:
- stage: publish
- image: $CI_REGISTRY_IMAGE/devcontainer:{{ cookiecutter.python_version }}-$CI_IMAGE_SHA
- script:
- {%- if cookiecutter.private_package_repository_name %}
- - poetry config repositories.private "{{ cookiecutter.private_package_repository_url.replace('simple/', '').replace('simple', '') }}"
- - poetry config http-basic.private "gitlab-ci-token" "$CI_JOB_TOKEN"
- - poetry publish --build --repository private
- {%- else %}
- - poetry config pypi-token.pypi "$POETRY_PYPI_TOKEN_PYPI"
- - poetry publish --build
- {%- endif %}
- only:
- - tags
-{%- else -%}
-# Deploy the app to the Docker registry.
-Deploy:
- stage: deploy
- image: docker:latest
- services:
- - docker:dind
- script:
- - |
- # Log in to the Docker registry.
- echo "$CI_REGISTRY_PASSWORD" | docker login --username "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
-
- # Compile a list of tags for the image.
- DOCKER_TAGS=""
- if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then DOCKER_TAGS="$DOCKER_TAGS latest"; fi
- if [ -n "$CI_COMMIT_TAG" ]; then DOCKER_TAGS="$DOCKER_TAGS $CI_COMMIT_TAG"; fi
- if [ -n "$CI_ENVIRONMENT_NAME" ]; then DOCKER_TAGS="$DOCKER_TAGS $CI_ENVIRONMENT_NAME"; fi
- DOCKER_TAGS_JOINED=""
- for DOCKER_TAG in $DOCKER_TAGS; do
- DOCKER_TAGS_JOINED="$DOCKER_TAGS_JOINED --tag $CI_REGISTRY_IMAGE:$DOCKER_TAG"
- done
-
- # Build the app image.
- {%- if cookiecutter.private_package_repository_name %}
- echo "[http-basic.{{ cookiecutter.private_package_repository_name|slugify }}]" >> auth.toml
- echo "username = \"gitlab-ci-token\"" >> auth.toml
- echo "password = \"$CI_JOB_TOKEN\"" >> auth.toml
- {%- endif %}
- docker build \
- --cache-from "type=registry,ref=$CI_REGISTRY_IMAGE/devcontainer:{{ cookiecutter.python_version }}-$CI_IMAGE_SHA" \
- --pull \
- {%- if cookiecutter.private_package_repository_name %}
- --secret id=poetry-auth,src=auth.toml \
- {%- endif %}
- --target app \
- $DOCKER_TAGS_JOINED \
- .
-
- # Push the tags to the Docker registry.
- for DOCKER_TAG in $DOCKER_TAGS; do
- docker push "$CI_REGISTRY_IMAGE:$DOCKER_TAG"
- done
- only:
- - tags
- when: manual
-{%- endif %}
\ No newline at end of file
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.pre-commit-config.yaml b/{{ cookiecutter.__project_name_kebab_case }}/.pre-commit-config.yaml
deleted file mode 100644
index 7bf220d0..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/.pre-commit-config.yaml
+++ /dev/null
@@ -1,88 +0,0 @@
-# https://pre-commit.com
-default_install_hook_types: [commit-msg, pre-commit]
-default_stages: [pre-commit, manual]
-fail_fast: true
-repos:
- - repo: meta
- hooks:
- - id: check-useless-excludes
- - repo: https://github.com/pre-commit/pygrep-hooks
- rev: v1.10.0
- hooks:
- - id: python-check-mock-methods
- - id: python-use-type-annotations
- - id: rst-backticks
- - id: rst-directive-colons
- - id: rst-inline-touching-normal
- - id: text-unicode-replacement-char
- - repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v5.0.0
- hooks:
- - id: check-added-large-files
- - id: check-ast
- - id: check-builtin-literals
- - id: check-case-conflict
- - id: check-docstring-first
- - id: check-illegal-windows-names
- - id: check-json
- - id: check-merge-conflict
- - id: check-shebang-scripts-are-executable
- - id: check-symlinks
- - id: check-toml
- - id: check-vcs-permalinks
- - id: check-xml
- - id: check-yaml
- - id: debug-statements
- - id: destroyed-symlinks
- - id: detect-private-key
- - id: end-of-file-fixer
- types: [python]
- - id: fix-byte-order-marker
- - id: mixed-line-ending
- - id: name-tests-test
- args: [--pytest-test-first]
- - id: trailing-whitespace
- types: [python]
- - repo: local
- hooks:
- {%- if cookiecutter.with_conventional_commits|int %}
- - id: commitizen
- name: commitizen
- entry: cz check
- args: [--commit-msg-file]
- require_serial: true
- language: system
- stages: [commit-msg]
- {%- endif %}
- - id: ruff-check
- name: ruff check
- entry: ruff check
- args: ["--force-exclude", "--extend-fixable=ERA001,F401,F841,T201,T203"{% if cookiecutter.development_environment == "simple" %}, "--fix-only"{% endif %}]
- require_serial: true
- language: system
- types_or: [python, pyi]
- - id: ruff-format
- name: ruff format
- entry: ruff format
- args: [--force-exclude]
- require_serial: true
- language: system
- types_or: [python, pyi]
- {%- if cookiecutter.development_environment == "strict" %}
- - id: shellcheck
- name: shellcheck
- entry: shellcheck
- args: [--check-sourced]
- language: system
- types: [shell]
- {%- endif %}
- - id: poetry-check
- name: poetry check
- entry: poetry check
- language: system
- pass_filenames: false
- - id: mypy
- name: mypy
- entry: mypy
- language: system
- types: [python]
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/Dockerfile b/{{ cookiecutter.__project_name_kebab_case }}/Dockerfile
deleted file mode 100644
index 7e9c9a25..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/Dockerfile
+++ /dev/null
@@ -1,136 +0,0 @@
-# syntax=docker/dockerfile:1
-ARG PYTHON_VERSION={{ cookiecutter.python_version }}
-FROM {{ cookiecutter.__docker_image }} AS base
-
-# Remove docker-clean so we can keep the apt cache in Docker build cache.
-RUN rm /etc/apt/apt.conf.d/docker-clean
-{%- if cookiecutter.development_environment == "strict" %}
-
-# Configure Python to print tracebacks on crash [1], and to not buffer stdout and stderr [2].
-# [1] https://docs.python.org/3/using/cmdline.html#envvar-PYTHONFAULTHANDLER
-# [2] https://docs.python.org/3/using/cmdline.html#envvar-PYTHONUNBUFFERED
-ENV PYTHONFAULTHANDLER=1
-ENV PYTHONUNBUFFERED=1
-{%- endif %}
-
-# Create a non-root user and switch to it [1].
-# [1] https://code.visualstudio.com/remote/advancedcontainers/add-nonroot-user
-ARG UID=1000
-ARG GID=$UID
-RUN groupadd --gid $GID user && \
- useradd --create-home --gid $GID --uid $UID user --no-log-init && \
- chown user /opt/
-USER user
-
-# Create and activate a virtual environment.
-ENV VIRTUAL_ENV=/opt/{{ cookiecutter.__project_name_kebab_case }}-env
-ENV PATH=$VIRTUAL_ENV/bin:$PATH
-RUN python -m venv $VIRTUAL_ENV
-
-# Set the working directory.
-WORKDIR /workspaces/{{ cookiecutter.__project_name_kebab_case }}/
-
-
-
-FROM base AS poetry
-
-USER root
-
-# Install Poetry in separate venv so it doesn't pollute the main venv.
-ENV POETRY_VERSION=2.0.1
-ENV POETRY_VIRTUAL_ENV=/opt/poetry-env
-RUN --mount=type=cache,target=/root/.cache/pip/ \
- python -m venv $POETRY_VIRTUAL_ENV && \
- $POETRY_VIRTUAL_ENV/bin/pip install poetry~=$POETRY_VERSION && \
- ln -s $POETRY_VIRTUAL_ENV/bin/poetry /usr/local/bin/poetry
-
-# Install compilers that may be required for certain packages or platforms.
-RUN --mount=type=cache,target=/var/cache/apt/ \
- --mount=type=cache,target=/var/lib/apt/ \
- apt-get update && \
- apt-get install --no-install-recommends --yes build-essential
-
-USER user
-
-# Install the run time Python dependencies in the virtual environment.
-COPY --chown=user:user poetry.lock* pyproject.toml /workspaces/{{ cookiecutter.__project_name_kebab_case }}/
-RUN mkdir -p /home/user/.cache/pypoetry/ && mkdir -p /home/user/.config/pypoetry/ && \
- mkdir -p src/{{ cookiecutter.__project_name_snake_case }}/ && touch src/{{ cookiecutter.__project_name_snake_case }}/__init__.py && touch README.md
-RUN --mount=type=cache,uid=$UID,gid=$GID,target=/home/user/.cache/pypoetry/ \
- {%- if cookiecutter.private_package_repository_name %}
- --mount=type=secret,id=poetry-auth,uid=$UID,gid=$GID,target=/home/user/.config/pypoetry/auth.toml \
- {%- endif %}
- poetry install --without test,dev --all-extras --no-interaction
-
-
-
-FROM poetry AS dev
-
-# Install development tools: curl, git, gpg, nodejs, ssh, starship, sudo, vim, and zsh.
-USER root
-RUN --mount=type=cache,target=/var/cache/apt/ \
- --mount=type=cache,target=/var/lib/apt/ \
- curl -fsSL https://deb.nodesource.com/setup_current.x | bash - && \
- apt-get update && \
- apt-get install --no-install-recommends --yes curl git gnupg nodejs ssh sudo vim zsh && \
- sh -c "$(curl -fsSL https://starship.rs/install.sh)" -- "--yes" && \
- usermod --shell /usr/bin/zsh user && \
- echo 'user ALL=(root) NOPASSWD:ALL' > /etc/sudoers.d/user && chmod 0440 /etc/sudoers.d/user
-RUN git config --system --add safe.directory '*'
-USER user
-
-# Install the development Python dependencies in the virtual environment.
-RUN --mount=type=cache,uid=$UID,gid=$GID,target=/home/user/.cache/pypoetry/ \
- {%- if cookiecutter.private_package_repository_name %}
- --mount=type=secret,id=poetry-auth,uid=$UID,gid=$GID,target=/home/user/.config/pypoetry/auth.toml \
- {%- endif %}
- poetry install --all-extras --no-interaction
-
-# Persist output generated during docker build so that we can restore it in the dev container.
-COPY --chown=user:user .pre-commit-config.yaml /workspaces/{{ cookiecutter.__project_name_kebab_case }}/
-RUN mkdir -p /opt/build/poetry/ && cp poetry.lock /opt/build/poetry/ && \
- git init && pre-commit install --install-hooks && \
- mkdir -p /opt/build/git/ && cp .git/hooks/commit-msg .git/hooks/pre-commit /opt/build/git/
-
-# Configure the non-root user's shell.
-ENV ANTIDOTE_VERSION=1.9.7
-RUN git clone --branch v$ANTIDOTE_VERSION --depth=1 https://github.com/mattmc3/antidote.git ~/.antidote/ && \
- echo 'zsh-users/zsh-syntax-highlighting' >> ~/.zsh_plugins.txt && \
- echo 'zsh-users/zsh-autosuggestions' >> ~/.zsh_plugins.txt && \
- echo 'source ~/.antidote/antidote.zsh' >> ~/.zshrc && \
- echo 'antidote load' >> ~/.zshrc && \
- echo 'eval "$(starship init zsh)"' >> ~/.zshrc && \
- echo 'HISTFILE=~/.history/.zsh_history' >> ~/.zshrc && \
- echo 'HISTSIZE=1000' >> ~/.zshrc && \
- echo 'SAVEHIST=1000' >> ~/.zshrc && \
- echo 'setopt share_history' >> ~/.zshrc && \
- echo 'bindkey "^[[A" history-beginning-search-backward' >> ~/.zshrc && \
- echo 'bindkey "^[[B" history-beginning-search-forward' >> ~/.zshrc && \
- mkdir ~/.history/ && \
- zsh -c 'source ~/.zshrc'
-{%- if cookiecutter.private_package_repository_name %}
-
-# Enable Poetry to read the private package repository credentials.
-RUN ln -s /run/secrets/poetry-auth /home/user/.config/pypoetry/auth.toml
-{%- endif %}
-{%- if cookiecutter.project_type == "app" %}
-
-
-
-FROM base AS app
-
-# Copy the virtual environment from the poetry stage.
-COPY --from=poetry $VIRTUAL_ENV $VIRTUAL_ENV
-
-# Copy the {{ cookiecutter.project_type }} source code to the working directory.
-COPY --chown=user:user . .
-
-# Expose the app.
-{%- if cookiecutter.with_typer_cli|int %}
-ENTRYPOINT ["/opt/{{ cookiecutter.__project_name_kebab_case }}-env/bin/{{ cookiecutter.__project_name_kebab_case }}"]
-CMD []
-{%- else %}
-ENTRYPOINT ["/opt/{{ cookiecutter.__project_name_kebab_case }}-env/bin/poe"]
-CMD [{% if cookiecutter.with_fastapi_api|int %}"api"{% else %}"app"{% endif %}]
-{%- endif %}
-{%- endif %}
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/README.md b/{{ cookiecutter.__project_name_kebab_case }}/README.md
deleted file mode 100644
index 2f14f8ba..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/README.md
+++ /dev/null
@@ -1,171 +0,0 @@
-[](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url={{ cookiecutter.project_url.replace("https://", "git@").replace(".com/", ".com:") if cookiecutter.private_package_repository_url else cookiecutter.project_url }}){% if cookiecutter.continuous_integration == "GitHub" %} [](https://github.com/codespaces/new/{{ cookiecutter.project_url.replace("https://github.com/", "") }}){% endif %}
-
-# {{ cookiecutter.project_name }}
-
-{{ cookiecutter.project_description }}
-{%- if cookiecutter.project_type == "package" or cookiecutter.with_typer_cli|int %}
-
-## Installing
-
-To install this package, run:
-
-```sh
-{% if cookiecutter.private_package_repository_name %}poetry add{% else %}pip install{% endif %} {{ cookiecutter.__project_name_kebab_case }}
-```
-{%- endif %}
-
-## Using
-{%- if cookiecutter.with_typer_cli|int %}
-
-To view the CLI help information, run:
-
-```sh
-{{ cookiecutter.__project_name_kebab_case }} --help
-```
-{%- elif cookiecutter.project_type == "app" %}
-
-To serve this app, run:
-
-```sh
-docker compose up app
-```
-{%- if cookiecutter.with_fastapi_api|int %}
-
-and open [localhost:8000](http://localhost:8000) in your browser.
-{%- endif %}
-
-Within the Dev Container this is equivalent to:
-
-```sh
-poe {% if cookiecutter.with_fastapi_api|int %}api{% else %}app{% endif %}
-```
-{%- else %}
-
-Example usage:
-
-```python
-import {{ cookiecutter.__project_name_snake_case }}
-
-...
-```
-{%- endif %}
-
-## Contributing
-
-
-Prerequisites
-
-
-1. Set up Git to use SSH
-
-{% if cookiecutter.continuous_integration == "GitLab" -%}
-1. [Generate an SSH key](https://docs.gitlab.com/ee/user/ssh.html#generate-an-ssh-key-pair) and [add the SSH key to your GitLab account](https://docs.gitlab.com/ee/user/ssh.html#add-an-ssh-key-to-your-gitlab-account).
-{%- else -%}
-1. [Generate an SSH key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#generating-a-new-ssh-key) and [add the SSH key to your GitHub account](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account).
-{%- endif %}
-1. Configure SSH to automatically load your SSH keys:
- ```sh
- cat << EOF >> ~/.ssh/config
-
- Host *
- AddKeysToAgent yes
- IgnoreUnknown UseKeychain
- UseKeychain yes
- ForwardAgent yes
- EOF
- ```
-
-
-
-
-2. Install Docker
-
-1. [Install Docker Desktop](https://www.docker.com/get-started).
- - _Linux only_:
- - Export your user's user id and group id so that [files created in the Dev Container are owned by your user](https://github.com/moby/moby/issues/3206):
- ```sh
- cat << EOF >> ~/.bashrc
-
- export UID=$(id --user)
- export GID=$(id --group)
- {%- if cookiecutter.private_package_repository_name %}
- export POETRY_AUTH_TOML_PATH="~/.config/pypoetry/auth.toml"
- {%- endif %}
- EOF
- ```
- {%- if cookiecutter.private_package_repository_name %}
- - _Windows only_:
- - Export the location of your private package repository credentials so that Docker Compose can load these as a [build and run time secret](https://docs.docker.com/compose/compose-file/compose-file-v3/#secrets-configuration-reference):
- ```bat
- setx POETRY_AUTH_TOML_PATH %APPDATA%\pypoetry\auth.toml
- ```
- {%- endif %}
-
-
-
-
-3. Install VS Code or PyCharm
-
-1. [Install VS Code](https://code.visualstudio.com/) and [VS Code's Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers). Alternatively, install [PyCharm](https://www.jetbrains.com/pycharm/download/).
-2. _Optional:_ install a [Nerd Font](https://www.nerdfonts.com/font-downloads) such as [FiraCode Nerd Font](https://github.com/ryanoasis/nerd-fonts/tree/master/patched-fonts/FiraCode) and [configure VS Code](https://github.com/tonsky/FiraCode/wiki/VS-Code-Instructions) or [configure PyCharm](https://github.com/tonsky/FiraCode/wiki/Intellij-products-instructions) to use it.
-
-
-{%- if cookiecutter.private_package_repository_name %}
-
-
-4. Configure Poetry to use the private package repository
-
-{% if cookiecutter.continuous_integration == "GitLab" -%}
-1. [Create a personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token) with the `api` scope and use it to [add your private package repository credentials to your Poetry's `auth.toml` file](https://python-poetry.org/docs/repositories/#configuring-credentials):
- ```toml
- # Linux: ~/.config/pypoetry/auth.toml
- # macOS: ~/Library/Application Support/pypoetry/auth.toml
- # Windows: C:\Users\%USERNAME%\AppData\Roaming\pypoetry\auth.toml
- [http-basic.{{ cookiecutter.private_package_repository_name|slugify }}]
- username = "{personal access token name}"
- password = "{personal access token}"
- ```
-{%- else -%}
-1. [Add your private package repository credentials to your Poetry's `auth.toml` file](https://python-poetry.org/docs/repositories/#configuring-credentials):
- ```toml
- # Linux: ~/.config/pypoetry/auth.toml
- # macOS: ~/Library/Application Support/pypoetry/auth.toml
- # Windows: C:\Users\%USERNAME%\AppData\Roaming\pypoetry\auth.toml
- [http-basic.{{ cookiecutter.private_package_repository_name|slugify }}]
- username = "{username}"
- password = "{password}"
- ```
-{%- endif %}
-
-
-{%- endif %}
-
-
-
-
-Development environments
-
-The following development environments are supported:
-{% if cookiecutter.continuous_integration == "GitHub" %}
-1. ⭐️ _GitHub Codespaces_: click on _Code_ and select _Create codespace_ to start a Dev Container with [GitHub Codespaces](https://github.com/features/codespaces).
-{%- endif %}
-1. ⭐️ _VS Code Dev Container (with container volume)_: click on [Open in Dev Containers](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url={{ cookiecutter.project_url.replace("https://", "git@").replace(".com/", ".com:") if cookiecutter.private_package_repository_url else cookiecutter.project_url }}) to clone this repository in a container volume and create a Dev Container with VS Code.
-1. _VS Code Dev Container_: clone this repository, open it with VS Code, and run Ctrl/⌘ + ⇧ + P → _Dev Containers: Reopen in Container_.
-1. _PyCharm Dev Container_: clone this repository, open it with PyCharm, [create a Dev Container with Mount Sources](https://www.jetbrains.com/help/pycharm/start-dev-container-inside-ide.html), and [configure an existing Python interpreter](https://www.jetbrains.com/help/pycharm/configuring-python-interpreter.html#widget) at `/opt/{{ cookiecutter.__project_name_kebab_case }}-env/bin/python`.
-1. _Terminal_: clone this repository, open it with your terminal, and run `docker compose up --detach dev` to start a Dev Container in the background, and then run `docker compose exec dev zsh` to open a shell prompt in the Dev Container.
-
-
-
-
-Developing
-{% if cookiecutter.with_conventional_commits|int %}
-- This project follows the [Conventional Commits](https://www.conventionalcommits.org/) standard to automate [Semantic Versioning](https://semver.org/) and [Keep A Changelog](https://keepachangelog.com/) with [Commitizen](https://github.com/commitizen-tools/commitizen).
-{%- endif %}
-- Run `poe` from within the development environment to print a list of [Poe the Poet](https://github.com/nat-n/poethepoet) tasks available to run on this project.
-- Run `poetry add {package}` from within the development environment to install a run time dependency and add it to `pyproject.toml` and `poetry.lock`. Add `--group test` or `--group dev` to install a CI or development dependency, respectively.
-- Run `poetry update` from within the development environment to upgrade all dependencies to the latest versions allowed by `pyproject.toml`.
-{%- if cookiecutter.with_conventional_commits|int %}
-- Run `cz bump` to bump the {{ cookiecutter.project_type }}'s version, update the `CHANGELOG.md`, and create a git tag.
-{%- endif %}
-
-
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/docker-compose.yml b/{{ cookiecutter.__project_name_kebab_case }}/docker-compose.yml
deleted file mode 100644
index 07c1e58d..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/docker-compose.yml
+++ /dev/null
@@ -1,80 +0,0 @@
-version: "3.9"
-
-services:
-
- devcontainer:
- build:
- context: .
- target: dev
- {%- if cookiecutter.private_package_repository_name %}
- secrets:
- - poetry-auth
- {%- endif %}
- args:
- PYTHON_VERSION: ${PYTHON_VERSION:-{{ cookiecutter.python_version }}}
- UID: ${UID:-1000}
- GID: ${GID:-1000}
- {%- if not cookiecutter.private_package_repository_name %}
- environment:
- - POETRY_PYPI_TOKEN_PYPI
- {%- else %}
- secrets:
- - poetry-auth
- {%- endif %}
- volumes:
- - ..:/workspaces
- - command-history-volume:/home/user/.history/
-
- dev:
- extends: devcontainer
- stdin_open: true
- tty: true
- entrypoint: []
- command:
- [
- "sh",
- "-c",
- "sudo chown user $$SSH_AUTH_SOCK && cp --update /opt/build/poetry/poetry.lock /workspaces/{{ cookiecutter.__project_name_kebab_case }}/ && mkdir -p /workspaces/{{ cookiecutter.__project_name_kebab_case }}/.git/hooks/ && cp --update /opt/build/git/* /workspaces/{{ cookiecutter.__project_name_kebab_case }}/.git/hooks/ && zsh"
- ]
- environment:
- {%- if not cookiecutter.private_package_repository_name %}
- - POETRY_PYPI_TOKEN_PYPI
- {%- endif %}
- - SSH_AUTH_SOCK=/run/host-services/ssh-auth.sock
- {%- if cookiecutter.with_fastapi_api|int %}
- ports:
- - "8000"
- {%- endif %}
- volumes:
- - ~/.gitconfig:/etc/gitconfig
- - ~/.ssh/known_hosts:/home/user/.ssh/known_hosts
- - ${SSH_AGENT_AUTH_SOCK:-/run/host-services/ssh-auth.sock}:/run/host-services/ssh-auth.sock
- profiles:
- - dev
- {%- if cookiecutter.project_type == "app" %}
-
- app:
- build:
- context: .
- target: app
- {%- if cookiecutter.private_package_repository_name %}
- secrets:
- - poetry-auth
- {%- endif %}
- tty: true
- {%- if cookiecutter.with_fastapi_api|int %}
- ports:
- - "8000:8000"
- {%- endif %}
- profiles:
- - app
- {%- endif %}
-{%- if cookiecutter.private_package_repository_name %}
-
-secrets:
- poetry-auth:
- file: "${POETRY_AUTH_TOML_PATH:-~/Library/Application Support/pypoetry/auth.toml}"
-{%- endif %}
-
-volumes:
- command-history-volume:
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml b/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml
deleted file mode 100644
index 8e602038..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml
+++ /dev/null
@@ -1,273 +0,0 @@
-[build-system] # https://python-poetry.org/docs/pyproject/#poetry-and-pep-517
-requires = ["poetry-core>=1.0.0"]
-build-backend = "poetry.core.masonry.api"
-
-[project] # https://packaging.python.org/en/latest/specifications/pyproject-toml/
-name = "{{ cookiecutter.__project_name_kebab_case }}"
-version = "0.0.0"
-description = "{{ cookiecutter.project_description }}"
-readme = "README.md"
-license-files = ["LICENSE*"]
-authors = [
- { name = "{{ cookiecutter.author_name }}", email = "{{ cookiecutter.author_email }}" },
-]
-requires-python = ">={{ cookiecutter.python_version }},<4.0"
-dependencies = [
- {%- if cookiecutter.with_fastapi_api|int %}
- "fastapi[all] (>=0.115.6)",
- "gunicorn (>=23.0.0)",
- {%- endif %}
- {%- if cookiecutter.project_type == "app" %}
- "poethepoet (>=0.32.1)",
- {%- endif %}
- {%- if cookiecutter.with_typer_cli|int %}
- "typer[all] (>=0.15.1)",
- {%- endif %}
- {%- if cookiecutter.with_fastapi_api|int %}
- "uvicorn[standard] (>=0.34.0)",
- {%- endif %}
-]
-{%- if cookiecutter.with_typer_cli|int %}
-
-[project.scripts] # https://python-poetry.org/docs/pyproject/#scripts
-{{ cookiecutter.__project_name_kebab_case }} = "{{ cookiecutter.__project_name_snake_case }}.cli:app"
-{%- endif %}
-
-[project.urls] # https://packaging.python.org/en/latest/specifications/well-known-project-urls/#well-known-labels
-homepage = "{{ cookiecutter.project_url }}"
-source = "{{ cookiecutter.project_url }}"
-{%- if cookiecutter.with_conventional_commits|int %}
-changelog = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}blob/main/CHANGELOG.md"
-{%- endif %}
-releasenotes = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}releases"
-documentation = "{{ cookiecutter.project_url }}"
-issues = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}issues"
-
-[tool.poetry.group.test.dependencies] # https://python-poetry.org/docs/managing-dependencies#dependency-groups
-{%- if cookiecutter.with_conventional_commits|int %}
-commitizen = ">=4.1.0"
-{%- endif %}
-coverage = { extras = ["toml"], version = ">=7.6.10" }
-mypy = ">=1.14.1"
-{%- if cookiecutter.project_type == "package" %}
-poethepoet = ">=0.32.1"
-{%- endif %}
-pre-commit = ">=4.0.1"
-pytest = ">=8.3.4"
-pytest-mock = ">=3.14.0"
-pytest-xdist = ">=3.6.1"
-ruff = ">=0.9.2"
-{%- if cookiecutter.development_environment == "strict" %}
-shellcheck-py = ">=0.10.0.1"
-typeguard = ">=4.4.1"
-{%- endif %}
-
-[tool.poetry.group.dev.dependencies] # https://python-poetry.org/docs/managing-dependencies#dependency-groups
-cruft = ">=2.16.0"
-ipykernel = ">=6.29.4"
-ipython = ">=8.18.0"
-ipywidgets = ">=8.1.2"
-pdoc = ">=15.0.1"
-{%- if cookiecutter.private_package_repository_name %}
-
-[[tool.poetry.source]]
-name = "pypi"
-priority = "default"
-
-[[tool.poetry.source]] # https://python-poetry.org/docs/repositories/#using-a-private-repository
-name = "{{ cookiecutter.private_package_repository_name|slugify }}"
-url = "{{ cookiecutter.private_package_repository_url }}"
-priority = "explicit"
-{%- endif %}
-{%- if cookiecutter.with_conventional_commits|int %}
-
-[tool.commitizen] # https://commitizen-tools.github.io/commitizen/config/
-bump_message = "bump: v$current_version → v$new_version"
-tag_format = "v$version"
-update_changelog_on_bump = true
-version_provider = "pep621"
-{%- endif %}
-
-[tool.coverage.report] # https://coverage.readthedocs.io/en/latest/config.html#report
-{%- if cookiecutter.development_environment == "strict" %}
-fail_under = 50
-{%- endif %}
-precision = 1
-show_missing = true
-skip_covered = true
-
-[tool.coverage.run] # https://coverage.readthedocs.io/en/latest/config.html#run
-branch = true
-command_line = "--module pytest"
-data_file = "reports/.coverage"
-source = ["src"]
-
-[tool.coverage.xml] # https://coverage.readthedocs.io/en/latest/config.html#xml
-output = "reports/coverage.xml"
-
-[tool.mypy] # https://mypy.readthedocs.io/en/latest/config_file.html
-junit_xml = "reports/mypy.xml"
-{%- if cookiecutter.with_fastapi_api|int %}
-plugins = "pydantic.mypy"
-{%- endif %}
-{%- if cookiecutter.development_environment == "strict" %}
-strict = true
-disallow_subclassing_any = false
-disallow_untyped_decorators = false
-{%- endif %}
-ignore_missing_imports = true
-pretty = true
-show_column_numbers = true
-show_error_codes = true
-show_error_context = true
-warn_unreachable = true
-{%- if cookiecutter.development_environment == "strict" and cookiecutter.with_fastapi_api|int %}
-
-[tool.pydantic-mypy] # https://pydantic-docs.helpmanual.io/mypy_plugin/#configuring-the-plugin
-init_forbid_extra = true
-init_typed = true
-warn_required_dynamic_aliases = true
-warn_untyped_fields = true
-{%- endif %}
-
-[tool.pytest.ini_options] # https://docs.pytest.org/en/latest/reference/reference.html#ini-options-ref
-addopts = "--color=yes --doctest-modules --exitfirst --failed-first{% if cookiecutter.development_environment == 'strict' %} --strict-config --strict-markers --typeguard-packages={{ cookiecutter.__project_name_snake_case }}{% endif %} --verbosity=2 --junitxml=reports/pytest.xml"
-{%- if cookiecutter.development_environment == "strict" %}
-filterwarnings = ["error", "ignore::DeprecationWarning"]
-{%- endif %}
-testpaths = ["src", "tests"]
-xfail_strict = true
-
-[tool.ruff] # https://docs.astral.sh/ruff/settings/
-fix = true
-line-length = 100
-src = ["src", "tests"]
-target-version = "py{{ cookiecutter.python_version.split('.')[:2]|join }}"
-
-[tool.ruff.format]
-docstring-code-format = true
-skip-magic-trailing-comma = true
-
-[tool.ruff.lint]
-select = ["ALL"]
-{%- if cookiecutter.development_environment == "strict" %}
-ignore = ["CPY", "FIX", "ARG001", "COM812", "D203", "D213", "E501", "PD008", "PD009", "RET504", "S101", "TD003"]
-{%- else %}
-ignore = ["CPY", "FIX", "T20", "ARG001", "COM812", "D203", "D213", "E501", "PD008", "PD009", "PGH003", "RET504", "S101", "TD003"]
-{%- endif %}
-unfixable = ["ERA001", "F401", "F841", "T201", "T203"]
-
-[tool.ruff.lint.flake8-annotations]
-allow-star-arg-any = true
-{%- if cookiecutter.development_environment == "simple" %}
-ignore-fully-untyped = true
-{%- endif %}
-
-[tool.ruff.lint.flake8-tidy-imports]
-ban-relative-imports = "all"
-
-[tool.ruff.lint.isort]
-split-on-trailing-comma = false
-{%- if cookiecutter.development_environment == "strict" %}
-
-[tool.ruff.lint.pycodestyle]
-max-doc-length = 100
-{%- endif %}
-
-[tool.ruff.lint.pydocstyle]
-convention = "{{ cookiecutter.__docstring_style|lower }}"
-
-[tool.poe.tasks] # https://github.com/nat-n/poethepoet
-{%- if cookiecutter.with_fastapi_api|int %}
-
- [tool.poe.tasks.api]
- help = "Serve the REST API"
- shell = """
- if [ $dev ]
- then {
- uvicorn \
- --host $host \
- --port $port \
- --reload \
- {{ cookiecutter.__project_name_snake_case }}.api:app
- } else {
- gunicorn \
- --access-logfile - \
- --bind $host:$port \
- --graceful-timeout 10 \
- --keep-alive 10 \
- --log-file - \
- --timeout 30 \
- --worker-class uvicorn.workers.UvicornWorker \
- --worker-tmp-dir /dev/shm \
- --workers 2 \
- {{ cookiecutter.__project_name_snake_case }}.api:app
- } fi
- """
-
- [[tool.poe.tasks.api.args]]
- help = "Bind socket to this host (default: 0.0.0.0)"
- name = "host"
- options = ["--host"]
- default = "0.0.0.0"
-
- [[tool.poe.tasks.api.args]]
- help = "Bind socket to this port (default: 8000)"
- name = "port"
- options = ["--port"]
- default = "8000"
-
- [[tool.poe.tasks.api.args]]
- help = "Enable development mode"
- type = "boolean"
- name = "dev"
- options = ["--dev"]
-{%- elif cookiecutter.project_type == "app" %}
-
- [tool.poe.tasks.app]
- help = "Serve the app"
-
- [[tool.poe.tasks.app.sequence]]
- cmd = "echo 'Serving app...'"
-{%- endif %}
-
- [tool.poe.tasks.docs]
- help = "Generate this {{ cookiecutter.project_type }}'s docs"
- cmd = """
- pdoc
- --docformat $docformat
- --output-directory $outputdirectory
- {{ cookiecutter.__project_name_snake_case }}
- """
-
- [[tool.poe.tasks.docs.args]]
- help = "The docstring style (default: {{ cookiecutter.__docstring_style|lower }})"
- name = "docformat"
- options = ["--docformat"]
- default = "{{ cookiecutter.__docstring_style|lower }}"
-
- [[tool.poe.tasks.docs.args]]
- help = "The output directory (default: docs)"
- name = "outputdirectory"
- options = ["--output-directory"]
- default = "docs"
-
- [tool.poe.tasks.lint]
- help = "Lint this {{ cookiecutter.project_type }}"
- cmd = """
- pre-commit run
- --all-files
- --color always
- """
-
- [tool.poe.tasks.test]
- help = "Test this {{ cookiecutter.project_type }}"
-
- [[tool.poe.tasks.test.sequence]]
- cmd = "coverage run"
-
- [[tool.poe.tasks.test.sequence]]
- cmd = "coverage report"
-
- [[tool.poe.tasks.test.sequence]]
- cmd = "coverage xml"
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/__init__.py b/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/__init__.py
deleted file mode 100644
index 092b9828..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-"""{{ cookiecutter.project_name }}."""
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/api.py b/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/api.py
deleted file mode 100644
index c624edaf..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/api.py
+++ /dev/null
@@ -1,32 +0,0 @@
-"""{{ cookiecutter.project_name }} REST API."""
-
-import asyncio
-import logging
-from collections.abc import AsyncGenerator
-from contextlib import asynccontextmanager
-
-from fastapi import FastAPI
-
-
-@asynccontextmanager
-async def lifespan(app: FastAPI) -> AsyncGenerator[None]:
- """Handle FastAPI startup and shutdown events."""
- # Startup events.
- for handler in logging.root.handlers:
- logging.root.removeHandler(handler)
- yield
- # Shutdown events.
-
-
-app = FastAPI(lifespan=lifespan)
-
-
-@app.get("/compute")
-async def compute(n: int = 42) -> int:
- """Compute the result of a CPU-bound function."""
-
- def fibonacci(n: int) -> int:
- return n if n <= 1 else fibonacci(n - 1) + fibonacci(n - 2)
-
- result = await asyncio.to_thread(fibonacci, n)
- return result
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/cli.py b/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/cli.py
deleted file mode 100644
index 142b1860..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/cli.py
+++ /dev/null
@@ -1,12 +0,0 @@
-"""{{ cookiecutter.project_name }} CLI."""
-
-import typer
-from rich import print
-
-app = typer.Typer()
-
-
-@app.command()
-def fire(name: str = "Chell") -> None:
- """Fire portal gun."""
- print(f"[bold red]Alert![/bold red] {name} fired [green]portal gun[/green] :boom:")
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/py.typed b/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/py.typed
deleted file mode 100644
index e69de29b..00000000
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/tests/__init__.py b/{{ cookiecutter.__project_name_kebab_case }}/tests/__init__.py
deleted file mode 100644
index 2c168973..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/tests/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-"""{{ cookiecutter.project_name }} test suite."""
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/tests/test_api.py b/{{ cookiecutter.__project_name_kebab_case }}/tests/test_api.py
deleted file mode 100644
index 34d0b5a9..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/tests/test_api.py
+++ /dev/null
@@ -1,14 +0,0 @@
-"""Test {{ cookiecutter.project_name }} REST API."""
-
-import httpx
-from fastapi.testclient import TestClient
-
-from {{ cookiecutter.__project_name_snake_case }}.api import app
-
-client = TestClient(app)
-
-
-def test_read_root() -> None:
- """Test that reading the root is successful."""
- response = client.get("/compute", params={"n": 7})
- assert httpx.codes.is_success(response.status_code)
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/tests/test_cli.py b/{{ cookiecutter.__project_name_kebab_case }}/tests/test_cli.py
deleted file mode 100644
index 7ff89f4f..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/tests/test_cli.py
+++ /dev/null
@@ -1,15 +0,0 @@
-"""Test {{ cookiecutter.project_name }} CLI."""
-
-from typer.testing import CliRunner
-
-from {{ cookiecutter.__project_name_snake_case }}.cli import app
-
-runner = CliRunner()
-
-
-def test_fire() -> None:
- """Test that the fire command works as expected."""
- name = "GLaDOS"
- result = runner.invoke(app, ["--name", name])
- assert result.exit_code == 0
- assert name in result.stdout
diff --git a/{{ cookiecutter.__project_name_kebab_case }}/tests/test_import.py b/{{ cookiecutter.__project_name_kebab_case }}/tests/test_import.py
deleted file mode 100644
index 9cdcbcc0..00000000
--- a/{{ cookiecutter.__project_name_kebab_case }}/tests/test_import.py
+++ /dev/null
@@ -1,8 +0,0 @@
-"""Test {{ cookiecutter.project_name }}."""
-
-import {{ cookiecutter.__project_name_snake_case }}
-
-
-def test_import() -> None:
- """Test that the {{ cookiecutter.project_type }} can be imported."""
- assert isinstance({{ cookiecutter.__project_name_snake_case }}.__name__, str)