diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 76d49f7..66b218f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,6 +34,13 @@ repos: pass_filenames: false language: system # use the project's own pyrefly install so versions stay in sync with pyproject.toml +# interrogate (docstring coverage) +- repo: https://github.com/econchick/interrogate + rev: 1.7.0 + hooks: + - id: interrogate + pass_filenames: false # config (incl. exclude paths) lives in pyproject.toml + # sqlfluff - repo: https://github.com/sqlfluff/sqlfluff rev: 3.5.0 diff --git a/Makefile b/Makefile index 6088feb..1b7cbe7 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ lock: format: uv run ruff format --check . -lint: lint-python lint-sql +lint: lint-python lint-sql lint-docstrings lint-python: uv run ruff check --output-format=github . @@ -47,6 +47,9 @@ lint-python: lint-sql: uv run sqlfluff lint . +lint-docstrings: + uv run interrogate + type: uv run pyrefly check diff --git a/README.md b/README.md index 36a7361..309d24e 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ The checks contained in this repo include (in the order in which they run): * `ruff` checks code for "lint" * `pyrefly` is used for static type checking * `sqlfluff` checks and fixes sql formatting and linting +* `interrogate` checks docstring coverage * `uv` checks on valid and aligned pyproject.toml and uv.lock files * `commitlint` enforces commit message conforms to [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/) format @@ -114,4 +115,3 @@ If you absolutely must commit without adhering to the prek hooks, then you can u * [ ] switch from `nox` to `tox` (tox is more widely used and prevents python abuse - e.g. setup.py can become too complicated) * make sure tox goes fast - https://hynek.me/articles/turbo-charge-tox/ * [ ] switch `coverage` to not report until the end and combine all coverage reports together into one -* [ ] add [`interrogate`](https://github.com/econchick/interrogate) to prek and test suite diff --git a/pyproject.toml b/pyproject.toml index 0abd667..c4a9477 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ df = [ [dependency-groups] dev = [ + "interrogate >=1.7.0,<2", "mkdocs >=1.6.0,<2", "mkdocs-material >=9.4.5,<10", "mkdocstrings[python] >=0.25.2,<1", @@ -41,6 +42,16 @@ dev = [ packages = ["src/sample"] +############# +# Interrogate +############# +[tool.interrogate] +fail-under = 100 +ignore-init-method = true +verbose = 1 +exclude = ["tests", "docs", "noxfile.py"] + + ########## # Coverage ########## diff --git a/src/sample/sample_with_extra_install.py b/src/sample/sample_with_extra_install.py index d44b3b2..ebaaba7 100644 --- a/src/sample/sample_with_extra_install.py +++ b/src/sample/sample_with_extra_install.py @@ -1,3 +1,7 @@ +""" +A placeholder module for sample content requiring the "df" extra install +""" + try: import pandas as pd except ImportError: @@ -7,6 +11,16 @@ class SampleWithExtraInstall(Sample): + """ + Sample class requiring the "df" extra install + """ + def sample_extra(self): + """ + Sample method which returns an empty pandas DataFrame + + Returns: + df (pandas.DataFrame): empty DataFrame + """ df = pd.DataFrame() return df diff --git a/uv.lock b/uv.lock index e500d47..27fa341 100644 --- a/uv.lock +++ b/uv.lock @@ -81,6 +81,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/46/bd/551ee6af426af84ca33e02622be722925c196608e9127d731ef17c47f06e/argcomplete-3.7.2-py3-none-any.whl", hash = "sha256:6029205678bdd9c1c728a155f5f9ecf5812393f969eef58807641a2bc2aa5b19", size = 43294, upload-time = "2026-08-06T04:53:20.246Z" }, ] +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, +] + [[package]] name = "babel" version = "2.18.0" @@ -938,6 +947,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, ] +[[package]] +name = "interrogate" +version = "1.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "click" }, + { name = "colorama" }, + { name = "py" }, + { name = "tabulate", version = "0.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "tabulate", version = "0.10.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/22/74f7fcc96280eea46cf2bcbfa1354ac31de0e60a4be6f7966f12cef20893/interrogate-1.7.0.tar.gz", hash = "sha256:a320d6ec644dfd887cc58247a345054fc4d9f981100c45184470068f4b3719b0", size = 159636, upload-time = "2024-04-07T22:30:46.217Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl", hash = "sha256:b13ff4dd8403369670e2efe684066de9fcb868ad9d7f2b4095d8112142dc9d12", size = 46982, upload-time = "2024-04-07T22:30:44.277Z" }, +] + [[package]] name = "jinja2" version = "3.1.6" @@ -1828,6 +1855,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/df/7c/409ced8866197da50e9bcb2c9bf101e3e9a35b98a851c0ccd2a44509eaa5/prek-0.5.2-py3-none-win_arm64.whl", hash = "sha256:0ebea4ef39f6446f6c414a5a506cde8942b17b5899f74cf90e352628085d4005", size = 5489643, upload-time = "2026-09-02T17:49:25.778Z" }, ] +[[package]] +name = "py" +version = "1.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/ff/fec109ceb715d2a6b4c4a85a61af3b40c723a961e8828319fbcb15b868dc/py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", size = 207796, upload-time = "2021-11-04T17:17:01.377Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378", size = 98708, upload-time = "2021-11-04T17:17:00.152Z" }, +] + [[package]] name = "pydantic" version = "2.13.5" @@ -2662,6 +2698,7 @@ df = [ [package.dev-dependencies] dev = [ + { name = "interrogate" }, { name = "mkdocs" }, { name = "mkdocs-material" }, { name = "mkdocstrings", extra = ["python"] }, @@ -2681,6 +2718,7 @@ provides-extras = ["df"] [package.metadata.requires-dev] dev = [ + { name = "interrogate", specifier = ">=1.7.0,<2" }, { name = "mkdocs", specifier = ">=1.6.0,<2" }, { name = "mkdocs-material", specifier = ">=9.4.5,<10" }, { name = "mkdocstrings", extras = ["python"], specifier = ">=0.25.2,<1" }, @@ -2749,6 +2787,39 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/47/d5/83c3eacdd6c3249fb5f8a0b5612ab10b661862e0df869951f45fd837448d/sqlfluff-3.5.0-py3-none-any.whl", hash = "sha256:6e5fb7a0c491676ded68912245fc0627e88f8b0e6290bd4b54a65ce735f69716", size = 921597, upload-time = "2025-10-18T19:33:05.839Z" }, ] +[[package]] +name = "tabulate" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090, upload-time = "2022-10-06T17:21:48.54Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252, upload-time = "2022-10-06T17:21:44.262Z" }, +] + +[[package]] +name = "tabulate" +version = "0.10.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.14' and sys_platform == 'emscripten'", + "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.10.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/46/58/8c37dea7bbf769b20d58e7ace7e5edfe65b849442b00ffcdd56be88697c6/tabulate-0.10.0.tar.gz", hash = "sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d", size = 91754, upload-time = "2026-03-04T18:55:34.402Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl", hash = "sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3", size = 39814, upload-time = "2026-03-04T18:55:31.284Z" }, +] + [[package]] name = "tblib" version = "3.2.2"