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