diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index a1d734f..ea121d2 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -1,5 +1,10 @@
-name: Lint
-on: [push]
+name: Run pre-commit hooks
+on:
+ # Running on pull-requests and new pushes to main
+ pull_request:
+ push:
+ branches:
+ - main
jobs:
lint:
@@ -11,12 +16,14 @@ jobs:
steps:
- uses: actions/checkout@v4
- - uses: actions/setup-python@v4
+ - uses: actions/setup-python@v5
with:
- python-version: '3.10'
+ python-version: '3.11'
+ cache: 'pip'
+ cache-dependency-path: pyproject.toml
- name: Install packages
- run: pip install -r requirements-dev.txt
+ run: pip install .[dev]
- name: Install pre-commit hooks
run: pre-commit install --install-hooks
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
new file mode 100644
index 0000000..6838632
--- /dev/null
+++ b/.github/workflows/test.yaml
@@ -0,0 +1,28 @@
+name: Test
+on:
+ pull_request:
+ push:
+ branches:
+ - main
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ shell: bash -l {0}
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+ cache: 'pip'
+ cache-dependency-path: pyproject.toml
+
+ - name: Install packages
+ run: pip install .[test]
+
+ - name: Run tests
+ run: pytest test
diff --git a/.gitignore b/.gitignore
index 10f5f48..587d4ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@ __pycache__/
# local irrelevant files
.idea
+.vscode
.DS_Store
# C extensions
diff --git a/.markdownlint.json b/.markdownlint.json
deleted file mode 100644
index f74ed4b..0000000
--- a/.markdownlint.json
+++ /dev/null
@@ -1,13 +0,0 @@
-// https://github.com/DavidAnson/markdownlint#optionsconfig
-// Disabling some rules here as we find them too restrictive.
-{
- "default": true, // Include all rules by defauls
- "line-length": false, // To allow working with soft wraps in editors
- "no-inline-html": { // Sometimes we need to use
html tags in GitHub markdown,
- // as it doesn't allow setting the image size with markdown tags
- "allowed_elements": ["details", "img"]
- },
- "ul-indent": false, // To allow indenting the whole list to distinguish it visually
- "no-multiple-blanks": false // To allow multiple blank lines between a header and
- // the previous paragraph
-}
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 963cdc2..59a69e9 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,6 +1,8 @@
+default_language_version:
+ python: python3.11
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.5.0
+ rev: v6.0.0
hooks:
- id: check-yaml
exclude: '\.*conda/.*'
@@ -13,35 +15,19 @@ repos:
- id: debug-statements
- id: check-added-large-files
- - repo: https://github.com/igorshubovych/markdownlint-cli
- rev: v0.38.0
- hooks:
- - id: markdownlint
-
- repo: https://github.com/populationgenomics/pre-commits
rev: "v0.1.3"
hooks:
- id: cpg-id-checker
- repo: https://github.com/astral-sh/ruff-pre-commit
- # Ruff version.
- rev: v0.6.2
+ rev: v0.15.12
hooks:
- id: ruff
- args: ["--fix"]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v1.8.0
+ rev: v1.20.2
hooks:
- id: mypy
- args:
- [
- --pretty,
- --show-error-codes,
- --no-strict-optional,
- --ignore-missing-imports,
- --install-types,
- --non-interactive,
- ]
- additional_dependencies: [types-PyYAML==6.0.4, types-toml]
+ args: [--pretty, --show-error-codes, --install-types, --non-interactive]
diff --git a/README.md b/README.md
index ed39d83..2ad52df 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,25 @@
# CPG Python Template
-Template repository based on the [CPG team-docs](https://github.com/populationgenomics/team-docs/blob/main/new_repository.md) content.
+General-purpose template for CPG Python repositories. Provides project structure, linting, type checking, testing, and CI out of the box. Works as a scripts-only repo (just linting, no installation) or as an installable package — see the comments at the top of `pyproject.toml`.
-This contains python and markdown linting configuration, and a github linting action.
-Before making a new repository based on this template, it may be worth auditing the versions of linting tools and GitHub Actions listed in _.pre-commit-config.yaml_ and _.github/workflows_.
+## What's included
+
+- `pyproject.toml` with hatchling build, ruff linting, mypy, pytest config
+- `.pre-commit-config.yaml` with ruff, mypy, and CPG ID checker hooks
+- GitHub Actions for linting and testing
+- `src/` layout with placeholder package
+- `test/` directory with pytest
+
+## Quick start
+
+1. Create a new repo from this template
+2. Rename `package_name` in `src/`, `pyproject.toml`, and hatch build config
+3. Update the project name, description, and repository URL in `pyproject.toml`
+4. Add your dependencies to `pyproject.toml`
+5. Install: `pip install .[dev]`
+6. Run linting: `pre-commit run --all-files`
+7. Run tests: `pytest test`
+
+## For cpg-flow workflows
+
+If you're building a cpg-flow pipeline, use the [cpg-flow-pipeline-template](https://github.com/populationgenomics/cpg-flow-pipeline-template) instead. It extends this template with stages, jobs, scripts, Docker builds, and Artifact Registry CI.
diff --git a/pull_request_template.md b/pull_request_template.md
new file mode 100644
index 0000000..2dd1fb9
--- /dev/null
+++ b/pull_request_template.md
@@ -0,0 +1,14 @@
+# Purpose
+
+ - < The reason for this PR >
+
+## Proposed Changes
+
+ -
+ -
+
+## Checklist
+
+- [ ] Related GitHub Issue created
+- [ ] Tests covering new change
+- [ ] Linting checks pass
diff --git a/pyproject.toml b/pyproject.toml
index a6eed25..1d0d7af 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,3 +1,53 @@
+# This template supports two use cases:
+# 1. Scripts repo — linting/formatting only, no installation required.
+# Remove the [build-system], [tool.hatch.*], and [project] sections;
+# keep everything from [tool.ruff] onward.
+# 2. Installable package — the default. Uses src/ layout with hatchling.
+# Replace "package_name" with your package name in [project], [tool.hatch.*],
+# and the src/ directory.
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.hatch.build.targets.wheel]
+packages = ["src/package_name"]
+
+[tool.hatch.build.targets.wheel.sources]
+"src" = ""
+
+[project]
+# TODO: replace with your project name
+name = "package_name"
+# TODO: replace with your project description
+description = "TODO: project description"
+readme = "README.md"
+requires-python = ">=3.10"
+version = "0.1.0"
+license = { file = "LICENSE" }
+classifiers = [
+ "Environment :: Console",
+ "Intended Audience :: Science/Research",
+ "License :: OSI Approved :: MIT License",
+ "Natural Language :: English",
+ "Operating System :: Unix",
+ "Programming Language :: Python",
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
+]
+dependencies = []
+
+[project.optional-dependencies]
+dev = ["pre-commit", "pytest", "bump-my-version"]
+test = ["pytest"]
+
+[project.urls]
+# TODO: replace with your project repository URL
+Repository = "https://github.com/populationgenomics/package_name"
+
+
+[tool.pytest.ini_options]
+testpaths = ["test"]
+
[tool.ruff]
line-length = 120
@@ -5,18 +55,19 @@ line-length = 120
quote-style = "single"
[tool.ruff.lint]
-# ignore pydocstyle, flake8-boolean-trap (FBT)
-select = ["A", "B", "C", "E", "F", "G", "I", "N", "Q", "S", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "ERA", "EXE", "ICN", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "UP", "YTT"]
+select = ["A", "B", "C", "E", "F", "G", "I", "N", "Q", "S", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "ERA", "EXE", "ICN", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "UP", "YTT"]
-fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "ERA", "EXE", "FBT", "ICN", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "UP", "YTT"]
+fixable = ["ALL"]
ignore = [
- "ANN101", # Missing type annotation for self in method
+ "ANN001", # Missing type annotation for function argument
"ANN201", # Missing return type annotation for public function
- "ANN401", # Dynamically typed expressions (typing.Any) are disallowed in `**kwargs`
+ "ANN204", # Missing type annotation for special method __init__
+ "ANN401", # Dynamically typed expressions (typing.Any) are disallowed
+ "COM812", # Trailing comma prohibited
"G004", # Logging statement uses f-string
- "PLW0603", # Using the global statement to update `` is discouraged
- "PT018", # Assertion should be broken down into multiple parts
+ "PLR0913", # Too many arguments in function definition
+ "PLR2004", # Magic value used in comparison
"Q000", # Single quotes found but double quotes preferred
"S101", # Use of assert detected
]
@@ -26,15 +77,7 @@ section-order = ["future", "standard-library", "third-party", "hail", "cpg", "fi
[tool.ruff.lint.isort.sections]
hail = ["hail", "hailtop"]
+cpg = ["cpg_flow", "cpg_utils", "cpg_infra", "metamist", "analysis_runner"]
-# Adjust these for each repository, e.g., removing those that should be
-# local rather than CPG. Also fill in extend_skip below if there are any
-# subdirectories that should be ignored.
-cpg = [
- "analysis_runner",
- "cpg_infra",
- "cpg_utils",
- "cpg_workflows",
- "gnomad",
- "metamist",
-]
+[tool.mypy]
+ignore_missing_imports = true
diff --git a/requirements-dev.txt b/requirements-dev.txt
deleted file mode 100644
index 5cb8b46..0000000
--- a/requirements-dev.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-bump2version
-black
-pre-commit
-pylint
diff --git a/src/package_name/__init__.py b/src/package_name/__init__.py
new file mode 100644
index 0000000..556358b
--- /dev/null
+++ b/src/package_name/__init__.py
@@ -0,0 +1 @@
+# TODO: put something here
diff --git a/test/test_placeholder.py b/test/test_placeholder.py
new file mode 100644
index 0000000..bb34f1b
--- /dev/null
+++ b/test/test_placeholder.py
@@ -0,0 +1,5 @@
+# TODO: put something here
+
+
+def test_placeholder():
+ assert True