From 934c4e61533b2a12f415a78d3ae133fa32315f86 Mon Sep 17 00:00:00 2001 From: alex furrier Date: Sat, 21 Jun 2025 12:54:52 -0700 Subject: [PATCH] Add stricter linting and type checking Makes ruff and mypy more opinionated to catch more issues early. The init script now updates the module name in ruff config automatically. --- pyproject.toml | 51 +++++++++++++++++++++++++++++++++++++++++ scripts/init_project.py | 4 ++++ src/example.py | 6 ++--- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 580d4e9..4657471 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,3 +32,54 @@ dev = [ [tool.hatch.build.targets.wheel] packages = ["src"] + +[tool.ruff] +line-length = 88 +target-version = "py39" + +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + "I", # isort + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "UP", # pyupgrade + "TID", # flake8-tidy-imports + "E402", # module-import-not-at-top-of-file + "N", # pep8-naming + "S", # flake8-bandit + "PTH", # flake8-use-pathlib + "RUF", # ruff-specific rules + "ICN", # flake8-import-conventions +] + +ignore = [ + "E501", # line too long (handled by line-length) + "TID252", # prefer absolute imports (keep relative for internal imports) + "S101", # assert used (acceptable in tests) +] + +[tool.ruff.lint.flake8-tidy-imports] +# Prevent specific problematic imports +banned-api = {} + +[tool.ruff.lint.isort] +known-first-party = ["python-collab-template"] + +[tool.mypy] +python_version = "3.9" +strict = true +warn_return_any = true +warn_unused_configs = true +disallow_untyped_defs = true +disallow_incomplete_defs = true +check_untyped_defs = true +disallow_untyped_decorators = true +no_implicit_optional = true +warn_redundant_casts = true +warn_unused_ignores = true +warn_no_return = true +warn_unreachable = true +strict_equality = true diff --git a/scripts/init_project.py b/scripts/init_project.py index 51dcb4f..25f3b14 100755 --- a/scripts/init_project.py +++ b/scripts/init_project.py @@ -195,6 +195,10 @@ def main() -> None: if "tool" in config and "hatch" in config["tool"] and "build" in config["tool"]["hatch"] and "targets" in config["tool"]["hatch"]["build"] and "wheel" in config["tool"]["hatch"]["build"]["targets"]: config["tool"]["hatch"]["build"]["targets"]["wheel"]["packages"] = [project_module_name] + # Update ruff known-first-party if ruff config exists + if "tool" in config and "ruff" in config["tool"] and "lint" in config["tool"]["ruff"] and "isort" in config["tool"]["ruff"]["lint"]: + config["tool"]["ruff"]["lint"]["isort"]["known-first-party"] = [project_module_name] + with open(pyproject_path, "wb") as f: tomli_w.dump(config, f) diff --git a/src/example.py b/src/example.py index 585dd36..1d82bcd 100644 --- a/src/example.py +++ b/src/example.py @@ -1,7 +1,7 @@ -from typing import List, Optional import statistics from dataclasses import dataclass from datetime import datetime +from typing import Optional @dataclass @@ -14,8 +14,8 @@ class DataPoint: def calculate_moving_average( - data: List[DataPoint], window_size: int = 3 -) -> List[float]: + data: list[DataPoint], window_size: int = 3 +) -> list[float]: """Calculate moving average of values. Args: