diff --git a/.github/workflows/arim_lint.yml b/.github/workflows/arim_lint.yml new file mode 100644 index 00000000..3a59f122 --- /dev/null +++ b/.github/workflows/arim_lint.yml @@ -0,0 +1,27 @@ +name: Run linter + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.11 + architecture: 'x64' + cache: 'pip' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install hatch + - name: Run linter + run: | + hatch run lint:check-gh diff --git a/.github/workflows/arim_test_lint.yml b/.github/workflows/arim_test.yml similarity index 83% rename from .github/workflows/arim_test_lint.yml rename to .github/workflows/arim_test.yml index bf90ec73..5c141d19 100644 --- a/.github/workflows/arim_test_lint.yml +++ b/.github/workflows/arim_test.yml @@ -1,7 +1,7 @@ # This workflow will install Python dependencies, run tests and lint with a variety of Python versions # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python -name: Python package +name: Run unit tests on: push: @@ -12,18 +12,20 @@ on: jobs: build: strategy: - fail-fast: false + fail-fast: true matrix: python-version: ["3.8", "3.9", "3.10", "3.11"] os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} + architecture: 'x64' + cache: 'pip' - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 66b16e7f..3150d826 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,16 +11,22 @@ There are many way you can contribute to arim, including: ## Developer installation -A developer installation requires extra packages for testing, the documentation and code quality. -The recommended method is to use an [editable installation](https://pip.pypa.io/en/stable/reference/pip_install/), as follows: +A developer installation requires extra packages for testing, running the code formatter and linter, and building the documentation. + +The recommended instructions are as follows. + +[Install hatch.](https://hatch.pypa.io/latest/install/) + +Clone arim repository locally. + +Create a new virtual environment and install the dependencies: -1) Duplicate code from git repository -2) In the root directory which contains ``setup.py``, type in a console: ``` -pip install -e .[dev] +cd arim +hatch env create ``` -The ``[dev]`` flags installs recommended packages for developement, as defined in ``extras_require`` in the file ``setup.py``. +To activate the virtual environment, use `hatch shell`. Refer to [Hatch documentation](https://hatch.pypa.io/latest/intro/) for further details. ## Code quality guidelines @@ -32,13 +38,18 @@ Meaningful variable and function names, with no or little abbreviation, are in p arim code follows the general guidelines defined in [Python PEP-8](https://www.python.org/dev/peps/pep-0008/), with the amendments defined in the following sections. -### Code formatting +### Code formatting and linting + +arim uses [black](https://black.readthedocs.io/en/stable/) code formatter and [ruff](https://docs.astral.sh/ruff/) linter. -Python code must be formatted using [black](https://black.readthedocs.io/en/stable/). -To format a Python file named ``myfile.py``, type in a terminal: +Format and lint: ``` -black myfile.py +hatch run lint:fmt ``` +To only check, without changing the code, use `hatch run lint:check`. + +The linter configuration is defined in `pyproject.toml`. + ### Docstring @@ -86,10 +97,11 @@ Unit tests ensure that a given function returns intended results at the time of Unit testing in arim is powered by [pytest](https://docs.pytest.org). The tests are defined in directory ``tests``. Consider adding new tests! -To run the tests, type in a terminal in the root directory which contains ``tests`` and ``arim``: - - pytest +To run the unit tests, use the following command: +``` +hatch run test +``` All tests must pass. ## Releasing @@ -103,7 +115,7 @@ To create a release: 5. Create a wheel package with ``` -python setup.py bdist_wheel +hatch build ``` The result is a `.whl` file in the directory ``dist``, for example ``arim-0.8-py3-none-any.whl``. diff --git a/pyproject.toml b/pyproject.toml index c98bf950..d3b868a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,25 +78,28 @@ python = ["3.8", "3.9", "3.10", "3.11"] [tool.hatch.envs.lint] detached = true dependencies = [ - "black>=23.1.0", - "mypy>=1.0.0", - "ruff>=0.0.243", + "black~=23.0", + "mypy==1.10.0", + "ruff==0.4.7", ] [tool.hatch.envs.lint.scripts] -typing = "mypy --install-types --non-interactive {args:src/arim tests}" -style = [ - "ruff {args:.}", +# typing = "mypy --install-types --non-interactive {args:src/arim tests}" +check = [ + "ruff check {args:.}", + "black --check --diff {args:.}", +] +check-gh = [ + "ruff check --output-format=github {args:.}", "black --check --diff {args:.}", ] fmt = [ "black {args:.}", - "ruff --fix {args:.}", - "style", -] -all = [ - "style", - "typing", + "ruff check --fix {args:.}", ] +# all = [ +# "check", +# "typing", +# ] [tool.black] target-version = ["py38"] @@ -105,7 +108,7 @@ line-length = 88 [tool.ruff] target-version = "py38" line-length = 88 -select = [ +lint.select = [ "E", "F", "NPY", @@ -113,23 +116,23 @@ select = [ "UP", "W", ] -ignore = [ +lint.ignore = [ "E731", # lambda are fine "E501", # line too long (in practice: only in comment or docstring) "NPY002", # legacy np.random API + "NPY201", # Temporary: np.complex_ will be removed in numpy 2.0 + "UP032", # Use f-string instead of `format` call + "UP031", # Use format specifiers instead of percent format ] -unfixable = [ +lint.unfixable = [ # Don't touch unused imports, because we may be reexporting the API in __init__.py "F401", ] -[tool.ruff.isort] +[tool.ruff.lint.isort] known-first-party = ["arim"] -[tool.ruff.flake8-tidy-imports] -ban-relative-imports = "all" - -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] # Tests can use magic values, assertions, and relative imports "tests/**/*" = ["PLR2004", "S101", "TID252"]