From 2362dac7b8d904631e58f86d19d34b84ff4387b1 Mon Sep 17 00:00:00 2001 From: "Pablo R. Mier" Date: Mon, 29 Apr 2024 22:09:39 +0200 Subject: [PATCH] Update deps and add CONTRIB guidelines --- CONTRIBUTING.md | 122 ++++++++++++++++++++++++++++++++++++++++++++++++ poetry.lock | 101 ++++++++++++++++++++++----------------- pyproject.toml | 5 +- 3 files changed, 182 insertions(+), 46 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..e431225b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,122 @@ +# Contributing to CORNETO + +Thank you for your interest in contributing to CORNETO! We are currently in the alpha phase of development, focusing on creating and testing core functionalities, and are also in the process of preparing a manuscript that details the novel methods included in the framework. Due to these activities, the project remains closed to public contributions to maintain a controlled and focused development environment. + +We value community input and look forward to opening up for contributions once we transition to a more stable beta phase. Please stay tuned for updates and feel free to provide feedback or express interest in contributing through GitHub issues. + +## Setup environment + +We use [Poetry](https://python-poetry.org) for dependency management. Please follow the instructions to install `poetry` on your system: https://python-poetry.org/docs/#installing-with-pipx. We recommend to install poetry using `pipx`. Once installed, clone the repository and install it with poetry. This will create a virtual environment ready for development: + +``` +git clone https://github.com/saezlab/corneto.git +cd corneto +poetry install +``` + +## Pre-commit Hooks + +We use pre-commit hooks to ensure that contributions meet our coding standards and to prevent common coding issues. Pre-commit is a framework that manages and maintains multi-language pre-commit hooks. + +### Using Ruff with Pre-commit + +We use `ruff`, a fast, modern linter for Python, as part of our pre-commit hooks. `ruff` helps in checking the style and quality of the Python code before it is committed to the repository. + +### Setting Up Pre-commit + +Follow these steps to set up pre-commit on your local development environment using Poetry: + +1. **Install the Git Hook Scripts**: + Run the following command in your repository to install the pre-commit hooks via Poetry: + ```bash + poetry run pre-commit install + ``` + +2. **Run Pre-commit**: + After setup, pre-commit will run automatically on git commit. However, you can manually run it on all files in the project to see if there are any issues: + ```bash + poetry run pre-commit run --all-files + ``` + + +### How It Works +When you commit changes, the pre-commit hook triggers ruff to check the staged files for style errors or other issues based on the defined rules. If ruff finds errors that it cannot automatically fix, the commit will be blocked until these errors are resolved. This helps maintain code quality and consistency across contributions. + +By incorporating ruff with pre-commit into our workflow, we streamline code reviews and maintain a high standard for code quality. Please ensure you have this setup in your local development environment to aid in smooth contributions to the project. + + +## Code Documentation Standards + +We adhere to Google's docstring style for documenting the Python code. + +### Google Docstring Style + +Docstrings should provide a clear explanation of the function's purpose, its arguments, what it returns, and any exceptions it raises. This includes: + +- A brief description of the function. +- A detailed list of parameters and their types. +- An explanation of the return type and what the function returns. +- Any exceptions that might be raised and under what conditions. + +### Example of documentation + +Below is an example of a function that adheres to the Google docstring style, which `ruff` will validate for compliance: + +```python +def calculate_division(numerator: float, denominator: float) -> float: + """ + Divides the numerator by the denominator and returns the result. + + Args: + numerator (float): The numerator of the division. + denominator (float): The denominator of the division; must not be zero. + + Returns: + float: The result of the division. + + Raises: + ValueError: If the denominator is zero. + + Examples: + >>> calculate_division(10, 2) + 5.0 + >>> calculate_division(5, 0) + Traceback (most recent call last): + ... + ValueError: Denominator cannot be zero. + """ + if denominator == 0: + raise ValueError("Denominator cannot be zero.") + return numerator / denominator +``` + +## Testing + +We use `pytest` for running our automated tests. To run tests, use Poetry to execute the tests by running: + +```bash +poetry run pytest +``` + +This command will run all test files in your project that follow the `test_*.py` or `*_test.py` naming conventions, as recognized by `pytest`. + +### Writing Tests + +When writing tests, ensure each test function is clear and focused on a specific functionality. Here’s an example of a simple test: + +```python +# tests/test_calculation.py + +def test_calculate_division(): + from calculations import calculate_division + assert calculate_division(10, 2) == 5.0 + with pytest.raises(ValueError): + calculate_division(5, 0) +``` + +### Best Practices for Testing + +- **Isolation**: Each test should be independent of others; changes in one test should not affect any other. +- **Coverage**: Aim for as much code coverage as possible to ensure that all code paths and scenarios are tested. +- **Documentation**: Document what each test covers and any specific scenarios it is testing. +- **Simplicity**: Keep tests simple and easy to understand. Complex tests can become a source of bugs themselves. diff --git a/poetry.lock b/poetry.lock index ebbc2bf7..b6c64c05 100644 --- a/poetry.lock +++ b/poetry.lock @@ -802,13 +802,13 @@ six = "*" [[package]] name = "docutils" -version = "0.19" +version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"}, - {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, ] [[package]] @@ -887,13 +887,13 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "filelock" -version = "3.13.4" +version = "3.14.0" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.13.4-py3-none-any.whl", hash = "sha256:404e5e9253aa60ad457cae1be07c0f0ca90a63931200a47d9b6a6af84fd7b45f"}, - {file = "filelock-3.13.4.tar.gz", hash = "sha256:d13f466618bfde72bd2c18255e269f72542c6e70e7bac83a0232d6b1cc5c8cf4"}, + {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, + {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, ] [package.extras] @@ -1448,20 +1448,20 @@ referencing = ">=0.31.0" [[package]] name = "jupyter-cache" -version = "0.6.1" +version = "1.0.0" description = "A defined interface for working with a cache of jupyter notebooks." optional = false -python-versions = "~=3.8" +python-versions = ">=3.9" files = [ - {file = "jupyter-cache-0.6.1.tar.gz", hash = "sha256:26f83901143edf4af2f3ff5a91e2d2ad298e46e2cee03c8071d37a23a63ccbfc"}, - {file = "jupyter_cache-0.6.1-py3-none-any.whl", hash = "sha256:2fce7d4975805c77f75bdfc1bc2e82bc538b8e5b1af27f2f5e06d55b9f996a82"}, + {file = "jupyter_cache-1.0.0-py3-none-any.whl", hash = "sha256:594b1c4e29b488b36547e12477645f489dbdc62cc939b2408df5679f79245078"}, + {file = "jupyter_cache-1.0.0.tar.gz", hash = "sha256:d0fa7d7533cd5798198d8889318269a8c1382ed3b22f622c09a9356521f48687"}, ] [package.dependencies] attrs = "*" click = "*" importlib-metadata = "*" -nbclient = ">=0.2,<0.8" +nbclient = ">=0.2" nbformat = "*" pyyaml = "*" sqlalchemy = ">=1.3.12,<3" @@ -1469,7 +1469,7 @@ tabulate = "*" [package.extras] cli = ["click-log"] -code-style = ["pre-commit (>=2.12,<4.0)"] +code-style = ["pre-commit (>=2.12)"] rtd = ["ipykernel", "jupytext", "myst-nb", "nbdime", "sphinx-book-theme", "sphinx-copybutton"] testing = ["coverage", "ipykernel", "jupytext", "matplotlib", "nbdime", "nbformat (>=5.1)", "numpy", "pandas", "pytest (>=6,<8)", "pytest-cov", "pytest-regressions", "sympy"] @@ -1966,25 +1966,25 @@ icu = ["PyICU (>=1.0.0)"] [[package]] name = "nbclient" -version = "0.7.4" +version = "0.10.0" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" files = [ - {file = "nbclient-0.7.4-py3-none-any.whl", hash = "sha256:c817c0768c5ff0d60e468e017613e6eae27b6fa31e43f905addd2d24df60c125"}, - {file = "nbclient-0.7.4.tar.gz", hash = "sha256:d447f0e5a4cfe79d462459aec1b3dc5c2e9152597262be8ee27f7d4c02566a0d"}, + {file = "nbclient-0.10.0-py3-none-any.whl", hash = "sha256:f13e3529332a1f1f81d82a53210322476a168bb7090a0289c795fe9cc11c9d3f"}, + {file = "nbclient-0.10.0.tar.gz", hash = "sha256:4b3f1b7dba531e498449c4db4f53da339c91d449dc11e9af3a43b4eb5c5abb09"}, ] [package.dependencies] jupyter-client = ">=6.1.12" jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" nbformat = ">=5.1" -traitlets = ">=5.3" +traitlets = ">=5.4" [package.extras] dev = ["pre-commit"] docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"] -test = ["flaky", "ipykernel", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] +test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] [[package]] name = "nbformat" @@ -2770,6 +2770,23 @@ dev = ["nox", "pre-commit", "pydata-sphinx-theme[doc,test]", "pyyaml"] doc = ["ablog (>=0.11.0rc2)", "colorama", "ipykernel", "ipyleaflet", "jupyter_sphinx", "jupyterlite-sphinx", "linkify-it-py", "matplotlib", "myst-parser", "nbsphinx", "numpy", "numpydoc", "pandas", "plotly", "rich", "sphinx-autoapi (>=3.0.0)", "sphinx-copybutton", "sphinx-design", "sphinx-favicon (>=1.0.1)", "sphinx-sitemap", "sphinx-togglebutton", "sphinxcontrib-youtube (<1.4)", "sphinxext-rediraffe", "xarray"] test = ["pytest", "pytest-cov", "pytest-regressions"] +[[package]] +name = "pydocstyle" +version = "6.3.0" +description = "Python docstring style checker" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, + {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, +] + +[package.dependencies] +snowballstemmer = ">=2.2.0" + +[package.extras] +toml = ["tomli (>=1.2.3)"] + [[package]] name = "pyflakes" version = "3.2.0" @@ -2842,13 +2859,13 @@ files = [ [[package]] name = "pytest" -version = "8.1.1" +version = "8.2.0" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"}, - {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"}, + {file = "pytest-8.2.0-py3-none-any.whl", hash = "sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233"}, + {file = "pytest-8.2.0.tar.gz", hash = "sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f"}, ] [package.dependencies] @@ -2856,11 +2873,11 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=1.4,<2.0" +pluggy = ">=1.5,<2.0" tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "python-dateutil" @@ -3585,22 +3602,22 @@ test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=6.0)", "setuptools [[package]] name = "sphinx-autodoc-typehints" -version = "1.23.0" +version = "1.25.3" description = "Type hints (PEP 484) support for the Sphinx autodoc extension" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "sphinx_autodoc_typehints-1.23.0-py3-none-any.whl", hash = "sha256:ac099057e66b09e51b698058ba7dd76e57e1fe696cd91b54e121d3dad188f91d"}, - {file = "sphinx_autodoc_typehints-1.23.0.tar.gz", hash = "sha256:5d44e2996633cdada499b6d27a496ddf9dbc95dd1f0f09f7b37940249e61f6e9"}, + {file = "sphinx_autodoc_typehints-1.25.3-py3-none-any.whl", hash = "sha256:d3da7fa9a9761eff6ff09f8b1956ae3090a2d4f4ad54aebcade8e458d6340835"}, + {file = "sphinx_autodoc_typehints-1.25.3.tar.gz", hash = "sha256:70db10b391acf4e772019765991d2de0ff30ec0899b9ba137706dc0b3c4835e0"}, ] [package.dependencies] -sphinx = ">=5.3" +sphinx = ">=7.1.2" [package.extras] -docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23.4)"] -testing = ["covdefaults (>=2.2.2)", "coverage (>=7.2.2)", "diff-cover (>=7.5)", "nptyping (>=2.5)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "sphobjinv (>=2.3.1)", "typing-extensions (>=4.5)"] -type-comment = ["typed-ast (>=1.5.4)"] +docs = ["furo (>=2023.9.10)"] +numpy = ["nptyping (>=2.5)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "sphobjinv (>=2.3.1)", "typing-extensions (>=4.8)"] [[package]] name = "sphinx-design" @@ -3708,21 +3725,21 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-bibtex" -version = "2.5.0" +version = "2.6.2" description = "Sphinx extension for BibTeX style citations." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "sphinxcontrib-bibtex-2.5.0.tar.gz", hash = "sha256:71b42e5db0e2e284f243875326bf9936aa9a763282277d75048826fef5b00eaa"}, - {file = "sphinxcontrib_bibtex-2.5.0-py3-none-any.whl", hash = "sha256:748f726eaca6efff7731012103417ef130ecdcc09501b4d0c54283bf5f059f76"}, + {file = "sphinxcontrib-bibtex-2.6.2.tar.gz", hash = "sha256:f487af694336f28bfb7d6a17070953a7d264bec43000a2379724274f5f8d70ae"}, + {file = "sphinxcontrib_bibtex-2.6.2-py3-none-any.whl", hash = "sha256:10d45ebbb19207c5665396c9446f8012a79b8a538cb729f895b5910ab2d0b2da"}, ] [package.dependencies] -docutils = ">=0.8" +docutils = ">=0.8,<0.18.dev0 || >=0.20.dev0" importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} pybtex = ">=0.24" pybtex-docutils = ">=1.0.0" -Sphinx = ">=2.1" +Sphinx = ">=3.5" [[package]] name = "sphinxcontrib-devhelp" @@ -4169,13 +4186,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.26.0" +version = "20.26.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.26.0-py3-none-any.whl", hash = "sha256:0846377ea76e818daaa3e00a4365c018bc3ac9760cbb3544de542885aad61fb3"}, - {file = "virtualenv-20.26.0.tar.gz", hash = "sha256:ec25a9671a5102c8d2657f62792a27b48f016664c6873f6beed3800008577210"}, + {file = "virtualenv-20.26.1-py3-none-any.whl", hash = "sha256:7aa9982a728ae5892558bff6a2839c00b9ed145523ece2274fad6f414690ae75"}, + {file = "virtualenv-20.26.1.tar.gz", hash = "sha256:604bfdceaeece392802e6ae48e69cec49168b9c5f4a44e483963f9242eb0e78b"}, ] [package.dependencies] @@ -4304,4 +4321,4 @@ recommended = ["cvxpy", "gurobipy", "matplotlib", "scipy"] [metadata] lock-version = "2.0" python-versions = ">=3.9 <4" -content-hash = "1cbf7988e7cfec6a9040dca2ce244855b36eac8aff9c07c5b6ab4a0fef9b4c1c" +content-hash = "fdceca08ff7a2dbbd8bb5bde81fef56f31d585dd42eaa67a4bf2f17ec701a449" diff --git a/pyproject.toml b/pyproject.toml index 753ae634..dd55dca5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,7 +67,7 @@ sphinx-hoverxref = "^1.3.0" pytest = "^8.1.1" flake8 = "^7.0.0" pre-commit = "^3.7.0" - +pydocstyle = "^6.3.0" [tool.poetry.extras] recommended = ["cvxpy", "scipy", "gurobipy", "matplotlib"] @@ -78,7 +78,6 @@ picos = ["PICOS"] networkx = ["networkx"] matplotlib = ["matplotlib"] - [tool.ruff] ignore-init-module-imports = true fix = true @@ -90,8 +89,6 @@ docstring-quotes = "double" [tool.ruff.pydocstyle] convention = "google" - [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" -