diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..88195a31 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,30 @@ +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.6.8 + hooks: + - id: ruff + alias: ruff-include-sorting + name: Check include sorting (ruff) + args: ['check', '--select', 'I', '--fix', '.'] + - id: ruff-format + name: Check formatting (ruff) + args: ['.'] + - id: ruff + alias: ruff-linting + name: Linting (ruff) + files: ^pedpy/ + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.11.2 # Use the latest version of mypy available at the time + hooks: + - id: mypy + name: Check type hints (mypy) + additional_dependencies: [ + "numpy~=2.1", + "pandas~=2.2.3", + "Shapely~=2.0.6", + "scipy~=1.14", + "matplotlib~=3.9", + "h5py~=3.11" + ] + exclude: "(^helper/|^docs/|^scripts/|^tests/)" diff --git a/docs/source/developer_guide.rst b/docs/source/developer_guide.rst index 1fab1e2e..a684c9d2 100644 --- a/docs/source/developer_guide.rst +++ b/docs/source/developer_guide.rst @@ -252,25 +252,43 @@ Only Pull Request with succeeding pipelines will be allowed to be merged into th Formatting/Linting ------------------ -Except from the functional requirements (see :ref:`Tests`) for changes in the code base, we also have some non-functional requirements. +Aside from the functional requirements (see :ref:`Tests`) for changes in the code base, we also have some non-functional requirements. These will also be checked in our CI process for each Pull Request. +To ensure compliance with these requirements, we have integrated pre-commit hooks into the repository. -1. **Code formatting:** -To ensure that your Pull Request may get accepted, make sure that the code is formatted with ``ruff format``. -We provide a helper script (``scripts/format.sh``) that will format every file in the correct manner. -To test it locally you can use ``scripts/check-format.sh``. +1. **Install Pre-Commit Hooks:** -2. **Type Hints:** +To simplify and automate formatting, linting, and type checking, we use pre-commit hooks. This will ensure that every commit is checked against our formatting, linting, and type hinting standards before being accepted. + +To set up the pre-commit hooks locally, run the following command: + +```bash +pip install pre-commit +pre-commit install +``` +Now, every time you commit changes, the hooks will automatically run, checking for issues related to formatting, linting, and type hints. + +.. note :: + + These pre-commit hooks may change your files, i.e., when the code needs some reformatting, make sure to add these new changes also to your commit. + Otherwise you will not be able to commit. + +2. **Code formatting:** +To ensure that your Pull Request may get accepted, make sure that the code is formatted with ``ruff``. +The pre-commit hooks, will automatically format your code according to our guide lines. +Alternatively, We provide a helper script (``scripts/format.sh``) that will format every file in the correct manner. + +3. **Type Hints:** We decided that every function, parameter, return value, etc. should be annotated with type hints, as they make it clearer for users what to expect and what is needed. For ensuring that no type hint is forgotten we use ``MyPy``. -This can be checked locally via ``python3 -m mypy --config-file mypy.ini pedpy/`` +This can be checked locally via ``python3 -m mypy .`` -3. **Linting:** +4. **Linting:** Linting in Python is an important process that helps ensure that our code is consistent and adheres to best practices. Linting tools like ``ruff`` analyze our code for potential errors, bad practices, and code smells. This helps us catch issues early on and prevents them from becoming bigger problems down the line. -4. **Docstring style:** (included in linting) +5. **Docstring style:** (included in linting) Make sure to check whether every of your new functions has a docstring. We decided to use Google-docstring style to be used in our project. You can use `ruff` to check if everything is correct locally. diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index 9e22eeda..00000000 --- a/mypy.ini +++ /dev/null @@ -1,43 +0,0 @@ -[mypy] -python_version = 3.10 -namespace_packages = True -ignore_missing_imports = False -check_untyped_defs = True -disallow_any_generics = True -disallow_incomplete_defs = True -no_implicit_optional = True -no_implicit_reexport = True -strict_equality = True -warn_redundant_casts = True -warn_unused_ignores = True -plugins = numpy.typing.mypy_plugin - -[mypy-matplotlib.*] -ignore_missing_imports = True - -[mypy-mpl_toolkits.*] -ignore_missing_imports = True - -[mypy-pandas.*] -ignore_missing_imports = True - -[mypy-pygeos.*] -ignore_missing_imports = True - -[mypy-shapely.*] -ignore_missing_imports = True - -[mypy-numpy.*] -ignore_missing_imports = True - -[mypy-scipy.*] -ignore_missing_imports = True - -[mypy-aenum.*] -ignore_missing_imports = True - -[mypy-setuptools.*] -ignore_missing_imports = True - -[mypy-h5py.*] -ignore_missing_imports = True diff --git a/pyproject.toml b/pyproject.toml index 435788fe..ed70937a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -185,3 +185,31 @@ max-locals = 20 max-statements = 50 ## Constant types to ignore when used as "magic values" (see: PLR2004). allow-magic-value-types = ["int", "str"] + +[tool.mypy] +python_version = "3.10" +namespace_packages = true +ignore_missing_imports = false +check_untyped_defs = true +disallow_any_generics = true +disallow_incomplete_defs = true +no_implicit_optional = true +no_implicit_reexport = true +strict_equality = true +warn_redundant_casts = true +warn_unused_ignores = false +plugins = ["numpy.typing.mypy_plugin"] +exclude = "^(helper|docs|scripts|tests)(/|$)" + +[[tool.mypy.overrides]] +module = [ + "matplotlib.*", + "mpl_toolkits.*", + "pandas.*", + "shapely.*", + "numpy.*", + "scipy.*", + "setuptools.*", + "h5py.*", +] +ignore_missing_imports = true diff --git a/requirements.txt b/requirements.txt index a37ead18..dab1369d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,3 +19,4 @@ build~=1.1 mypy~=1.11 mypy-extensions==1.0 ruff~=0.6 +pre-commit~=3.8 diff --git a/scripts/check-format.sh b/scripts/check-format.sh deleted file mode 100755 index b383f73c..00000000 --- a/scripts/check-format.sh +++ /dev/null @@ -1,19 +0,0 @@ -#! /bin/bash - -location="$(cd "$(dirname "${0}")";pwd -P)" -root="$(cd "$(dirname "${location}/../..")";pwd -P)" - -njobs=1 -if [[ "$(uname)" == "Darwin" ]]; then - njobs=$(sysctl -n hw.logicalcpu) -elif [[ "$(uname)" == "Darwin" ]]; then - njobs=$(nproc) -fi - - -return_code=0 - -python -m ruff check --select I "${root}" || return_code=1 -ruff format --check "${root}" || return_code=1 - -exit ${return_code} diff --git a/scripts/ci.sh b/scripts/ci.sh index 9389ce15..6a565c0a 100755 --- a/scripts/ci.sh +++ b/scripts/ci.sh @@ -1,4 +1,4 @@ -#! /bin/bash +#!/bin/bash check_for_failure() { "$@" || failure=1 @@ -7,16 +7,8 @@ check_for_failure() { location="$(cd "$(dirname "${0}")";pwd -P)" root="$(cd "$(dirname "${location}/../..")";pwd -P)" -echo "Check format" -check_for_failure "${root}"/scripts/check-format.sh -echo "-------------------------------------------------------------------------" - -echo "Check typing with mypy" -check_for_failure python3 -m mypy --config-file mypy.ini pedpy/ -echo "-------------------------------------------------------------------------" - -echo "Linting with ruff" -check_for_failure python3 -m ruff check pedpy +echo "Running pre-commit checks..." +check_for_failure pre-commit run --all-files echo "-------------------------------------------------------------------------" if ((failure)); then