diff --git a/.cruft.json b/.cruft.json index 01a9e689..0f52c9b6 100644 --- a/.cruft.json +++ b/.cruft.json @@ -1,6 +1,6 @@ { "template": "https://github.com/Ouranosinc/cookiecutter-pypackage", - "commit": "240a2c784f89cb1e2c5952869413c5582e590345", + "commit": "de751c55cd9a5df586e3d961535292cfb73e0397", "checkout": null, "context": { "cookiecutter": { @@ -14,6 +14,7 @@ "version": "0.2.0", "use_pytest": "y", "use_black": "y", + "use_conda": "y", "add_pyup_badge": "n", "make_docs": "y", "command_line_interface": "Click", diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..1116575b --- /dev/null +++ b/.flake8 @@ -0,0 +1,30 @@ +[flake8] +exclude = + .eggs, + .git, + build, + docs, + tests +ignore = + AZ100, + AZ200, + AZ300, + C, + D, + E, + F, + W503 +per-file-ignores = +rst-roles = + doc, + mod, + py:attr, + py:attribute, + py:class, + py:const, + py:data, + py:func, + py:meth, + py:mod, + py:obj, + py:ref diff --git a/.github/workflows/actions-versions-updater.yml b/.github/workflows/actions-versions-updater.yml new file mode 100644 index 00000000..bb05b24e --- /dev/null +++ b/.github/workflows/actions-versions-updater.yml @@ -0,0 +1,24 @@ +name: GitHub Actions Version Updater + +on: + schedule: + # 12:00 AM on the first of every month + - cron: '0 0 1 * *' + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.1.1 + with: + # This requires a personal access token with the privileges to push directly to `main` + token: ${{ secrets.WORKFLOW_TOKEN }} + persist-credentials: true + - name: Run GitHub Actions Version Updater + uses: saadmk11/github-actions-version-updater@v0.8.1 + with: + token: ${{ secrets.WORKFLOW_TOKEN }} + committer_email: 'bumpversion[bot]@ouranos.ca' + committer_username: 'update-github-actions[bot]' + pull_request_title: '[bot] Update GitHub Action Versions' diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml new file mode 100644 index 00000000..3376401d --- /dev/null +++ b/.github/workflows/bump-version.yml @@ -0,0 +1,58 @@ +name: "Bump Patch Version" + +on: + push: + branches: + - main + paths-ignore: + - .cruft.json + - .editorconfig + - .github/**.yml + - .gitignore + - .pre-commit-config.yaml + - .yamllint.yaml + - .zenodo.json + - AUTHORS.rst + - CONTRIBUTING.rst + - CHANGES.rst + - Makefile + - .readthedocs.yml + - docs/*.py + - docs/*.rst + - environment-docs.yml + - environment-dev.yml + - setup.cfg + - pyproject.toml + - tests/**.py + - tox.ini + - figanos/__init__.py + workflow_dispatch: + +jobs: + bump_patch_version: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: Config Commit Bot + run: | + git config --local user.email "bumpversion[bot]@ouranos.ca" + git config --local user.name "bumpversion[bot]" + - name: Current Version + run: echo "current_version=$(grep -E '__version__' figanos/__init__.py | cut -d ' ' -f3)" + - name: Bump Patch Version + run: | + pip install bump-my-version + echo "Bumping version" + bump-my-version bump patch + echo "new_version=$(grep -E '__version__' figanos/__init__.py | cut -d ' ' -f3)" + - name: Push Changes + uses: ad-m/github-push-action@master + with: + force: false + github_token: ${{ secrets.WORKFLOW_TOKEN }} + branch: ${{ github.ref }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0a528328..bf00d77c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,40 +5,41 @@ on: branches: - main paths-ignore: - - HISTORY.rst - - MANIFEST.in + - CHANGES.rst - README.rst - - setup.py + - pyproject.toml - setup.cfg - figanos/__init__.py pull_request: jobs: - black: - name: Black (Python${{ matrix.python-version }}) + lint: + name: Lint (Python${{ matrix.python-version }}) runs-on: ubuntu-latest strategy: matrix: python-version: - - "3.8" + - "3.x" steps: - name: Cancel previous runs uses: styfle/cancel-workflow-action@0.11.0 with: access_token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install tox - run: pip install tox + run: | + python -m pip install tox - name: Run linting suite - run: tox -e black + run: | + python -m tox -e lint - test: - name: test-${{ matrix.tox-env }} (Python${{ matrix.python-version }}) - needs: black + test-pypi: + name: Test with Python${{ matrix.python-version }} (Python${{ matrix.python-version }} + tox) + needs: lint runs-on: ubuntu-latest strategy: matrix: @@ -52,38 +53,76 @@ jobs: - tox-env: "py311" python-version: "3.11" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} -# - name: Install tox -# run: pip install tox -# - name: Test with tox -# run: tox -e ${{ matrix.tox-env }} -# env: -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -# COVERALLS_FLAG_NAME: run-${{ matrix.tox-env }} -# COVERALLS_PARALLEL: true -# COVERALLS_SERVICE_NAME: github - - name: Install figanos (no dependencies) + - name: Install GDAL + run: | + sudo apt-get update + sudo apt-get install -y libgdal-dev + - name: Install tox + run: pip install tox + - name: Test with tox + run: tox -e ${{ matrix.tox-env }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COVERALLS_FLAG_NAME: run-${{ matrix.tox-env }} + COVERALLS_PARALLEL: true + COVERALLS_SERVICE_NAME: github + + test-conda: + name: Test with Python${{ matrix.python-version }} (Anaconda) + needs: lint + runs-on: ubuntu-latest + defaults: + run: + shell: bash -l {0} + steps: + - uses: actions/checkout@v4 + - name: Setup Conda (Micromamba) with Python${{ matrix.python-version }} + uses: mamba-org/setup-micromamba@v1 + with: + cache-downloads: true + environment-file: environment-dev.yml + create-args: >- + mamba + python=3.11 + - name: Conda and Mamba versions + run: | + mamba --version + echo "micromamba $(micromamba --version)" + - name: Compile catalogs and install xscen + run: | + python -m pip install --no-deps . + - name: Check versions + run: | + conda list + python -m pip check || true + - name: Test with pytest run: | - python -m pip install -e . --no-dependencies - - name: Smoke tests + python -m pytest --cov figanos + - name: Report coverage run: | - python -m pip install pytest - pytest + python -m coveralls + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COVERALLS_FLAG_NAME: run-py311-conda + COVERALLS_PARALLEL: true + COVERALLS_SERVICE_NAME: github -# finish: -# needs: -# - test -# runs-on: ubuntu-latest -# container: python:3-slim -# steps: -# - name: Coveralls Finished -# run: | -# pip install --upgrade coveralls -# coveralls --finish -# env: -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -# COVERALLS_SERVICE_NAME: github + finish: + needs: + - test-pypi + - test-conda + runs-on: ubuntu-latest + container: python:3-slim + steps: + - name: Coveralls Finished + run: | + python -m pip install --upgrade coveralls + python -m coveralls --finish + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COVERALLS_SERVICE_NAME: github diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 08a5bf77..fd8758a5 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -8,22 +8,22 @@ on: jobs: build-n-publish-pypi: name: Build and publish Python 🐍 distributions 📦 to PyPI - environment: production runs-on: ubuntu-latest + environment: production permissions: # IMPORTANT: this permission is mandatory for trusted publishing id-token: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python3 uses: actions/setup-python@v4 with: python-version: "3.x" - name: Install packaging libraries run: | - pip install setuptools wheel + python -m pip install flit - name: Build a binary wheel and a source tarball run: | - python setup.py sdist bdist_wheel + python -m flit build - name: Publish distribution 📦 to PyPI uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/tag-testpypi.yml b/.github/workflows/tag-testpypi.yml index ef6c5894..be281ae7 100644 --- a/.github/workflows/tag-testpypi.yml +++ b/.github/workflows/tag-testpypi.yml @@ -3,28 +3,47 @@ name: Publish Python 🐍 distributions 📦 to TestPyPI on: push: tags: - - '*' + - 'v*.*' # Push events to matching v*, i.e. v1.0, v20.15.10 jobs: - build-n-publish-testpypi: + + release: + name: Create Release from tag + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '.0') + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Create Release + uses: softprops/action-gh-release@v1 + env: + # This token is provided by Actions, you do not need to create your own token + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + name: Release ${{ github.ref }} + draft: true + prerelease: false + + deploy-testpypi: name: Build and publish Python 🐍 distributions 📦 to TestPyPI - environment: staging runs-on: ubuntu-latest + environment: staging permissions: # IMPORTANT: this permission is mandatory for trusted publishing id-token: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python3 uses: actions/setup-python@v4 with: python-version: "3.x" - name: Install packaging libraries run: | - pip install setuptools wheel + python -m pip install flit - name: Build a binary wheel and a source tarball run: | - python setup.py sdist bdist_wheel + python -m flit build - name: Publish distribution 📦 to Test PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 61605ddd..024c6781 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,15 +11,19 @@ repos: rev: v4.5.0 hooks: - id: trailing-whitespace - exclude: setup.cfg - id: end-of-file-fixer - id: debug-statements - id: check-json - id: pretty-format-json args: [ '--autofix', '--no-ensure-ascii', '--no-sort-keys' ] exclude: .ipynb + - id: check-toml - id: check-yaml args: [ '--allow-multiple-documents' ] + - repo: https://github.com/pappasam/toml-sort + rev: v0.23.1 + hooks: + - id: toml-sort-fix - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: @@ -29,23 +33,22 @@ repos: hooks: - id: black exclude: ^docs/ - - repo: https://github.com/pycqa/flake8 - rev: 6.1.0 - hooks: - - id: flake8 - additional_dependencies: [ 'flake8-rst-docstrings' ] - args: ['--config=setup.cfg'] - repo: https://github.com/PyCQA/isort rev: 5.12.0 hooks: - id: isort args: [ '--profile=black', '--filter-files', "--add_imports='from __future__ import annotations'" ] exclude: ^docs/ - - repo: https://github.com/pycqa/pydocstyle - rev: 6.3.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.4 hooks: - - id: pydocstyle - args: [ '--convention=numpy', '--match="(?!test_).*\.py"' ] + - id: ruff + - repo: https://github.com/pycqa/flake8 + rev: 6.1.0 + hooks: + - id: flake8 + additional_dependencies: [ 'flake8-alphabetize', 'flake8-rst-docstrings' ] + args: [ '--config=.flake8' ] - repo: https://github.com/keewis/blackdoc rev: v0.3.9 hooks: @@ -57,21 +60,16 @@ repos: - id: nbstripout files: '.ipynb' args: [ '--extra-keys=metadata.kernelspec' ] - - repo: https://github.com/pycqa/pydocstyle - rev: 6.3.0 - hooks: - - id: pydocstyle - args: [ '--config=setup.cfg' ] - repo: https://github.com/adrienverge/yamllint.git rev: v1.33.0 hooks: - id: yamllint args: [ '--config-file=.yamllint.yaml' ] -# Git version too old on server -# - repo: https://github.com/mgedmin/check-manifest -# rev: "0.49" -# hooks: -# - id: check-manifest + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.27.1 + hooks: + - id: check-github-workflows + - id: check-readthedocs - repo: meta hooks: - id: check-hooks-apply diff --git a/.readthedocs.yml b/.readthedocs.yml index d812bec2..9738fc25 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -22,7 +22,7 @@ build: - sphinx-apidoc -o docs/apidoc --module-first figanos conda: - environment: environment.yml + environment: environment-dev.yml python: install: diff --git a/HISTORY.rst b/CHANGES.rst similarity index 78% rename from HISTORY.rst rename to CHANGES.rst index d114f606..b210bd1a 100644 --- a/HISTORY.rst +++ b/CHANGES.rst @@ -1,6 +1,6 @@ -======= -History -======= +========= +Changelog +========= 0.3.0 (Unreleased) ------------------ @@ -15,6 +15,7 @@ New features and enhancements * Logo plotting now supports both PNG and SVG file types (via `cairosvg`). (:pull:`119`). * Use small geojson in the notebook. (:pull:`124`). * Add the Colours of Figanos page (:issue:`126`, :pull:`127`). +* Figanos now adheres to PEPs 517/518/621 using the `flit` backend for building and packaging. (:pull:`135`). Bug fixes ^^^^^^^^^ @@ -30,10 +31,20 @@ Internal changes * Cleaned up the docstrings of a few functions, added some module-level strings, minor typo fixes. * Set `nbsphinx` in the documentation to always run (with th exception of one complex cell). * The `environment.yml` Python version is set to 3.11 to reduce the dependency solver complexity. +* The `cookiecutter` template has been updated to the latest commit via `cruft`. (:pull:`138`): + * `Manifest.in`, `requirements_dev.txt`, `requirements_docs.txt` and `setup.py` have been removed. + * `pyproject.toml` has been added, with most package configurations migrated into it. + * `HISTORY.rst` has been renamed to `CHANGES.rst`. + * `actions-version-updater.yml` has been added to automate the versioning of the package. + * `bump-version.yml` has been added to automate patch versioning of the package. + * `pre-commit` hooks have been updated to the latest versions; `check-toml` and `toml-sort` have been added to cleanup the `pyproject.toml` file. + * `ruff` has been added to the linting tools to replace most `flake8` and `pydocstyle` verifications. + * GitHub workflows now run proper pytest suites for `conda`-based testing. Bug fixes ^^^^^^^^^ * Fixed an issue with the `divergent` argument getting ignored (:pull:`132`). +* Some small documentation fixes for working uniquely in a `conda` environment. (:pull:`138`). 0.2.0 (2023-06-19) ------------------ diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 4df44c47..eecc4b12 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -4,8 +4,7 @@ Contributing ============ -Contributions are welcome, and they are greatly appreciated! Every little bit -helps, and credit will always be given. +Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given. You can contribute in many ways: @@ -26,21 +25,17 @@ If you are reporting a bug, please include: Fix Bugs ~~~~~~~~ -Look through the GitHub issues for bugs. Anything tagged with "bug" and "help -wanted" is open to whoever wants to implement it. +Look through the GitHub issues for bugs. Anything tagged with "bug" and "help wanted" is open to whoever wants to implement it. Implement Features ~~~~~~~~~~~~~~~~~~ -Look through the GitHub issues for features. Anything tagged with "enhancement" -and "help wanted" is open to whoever wants to implement it. +Look through the GitHub issues for features. Anything tagged with "enhancement" and "help wanted" is open to whoever wants to implement it. Write Documentation ~~~~~~~~~~~~~~~~~~~ -figanos could always use more documentation, whether as part of the -official figanos docs, in docstrings, or even on the web in blog posts, -articles, and such. +``figanos`` could always use more documentation, whether as part of the official ``figanos`` docs, in docstrings, or even on the web in blog posts, articles, and such. Submit Feedback ~~~~~~~~~~~~~~~ @@ -57,20 +52,20 @@ If you are proposing a feature: Get Started! ------------------------------------------------- -Ready to contribute? Here's how to set up `figanos` for local development for developers outside Ouranos. +Ready to contribute? Here's how to set up ``figanos`` for local development for developers outside Ouranos. -1. Fork the `figanos` repo on GitHub. -2. Clone your fork locally:: +#. Fork the ``figanos`` repo on GitHub. +#. Clone your fork locally:: $ git clone git@github.com:your_name_here/figanos.git -3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: +#. Install your local copy into a development environment. Using ``mamba``, you can create a new development environment with:: - $ mkvirtualenv figanos - $ cd figanos/ - $ pip install -e . + $ mamba env create -f environment-dev.yml + $ conda activate figanos + $ flit install --symlink -4. To ensure a consistent style, please install the pre-commit hooks to your repo:: +#. To ensure a consistent style, please install the pre-commit hooks to your repo:: $ pre-commit install @@ -79,47 +74,50 @@ Ready to contribute? Here's how to set up `figanos` for local development for de $ pre-commit run -a -5. Create a branch for local development:: +#. Create a branch for local development:: $ git checkout -b name-of-your-bugfix-or-feature Now you can make your changes locally. -6. When you're done making changes, check that your changes pass flake8, black, and the - tests, including testing other Python versions with tox:: +#. When you're done making changes, check that your changes pass ``black``, ``blackdoc``, ``flake8``, ``isort``, ``ruff``, and the tests, including testing other Python versions with tox:: - $ flake8 figanos tests $ black --check figanos tests - $ python setup.py test or pytest + $ isort --check figanos tests + $ ruff figanos tests + $ flake8 figanos tests + $ blackdoc --check figanos docs + $ python -m pytest $ tox - To get flake8, black, and tox, just pip install them into your virtualenv. + To get ``black``, ``blackdoc``, ``flake8``, ``isort``, ``ruff``, and tox, just pip install them into your virtualenv. -6. Commit your changes and push your branch to GitHub:: +#. Commit your changes and push your branch to GitHub:: $ git add . $ git commit -m "Your detailed description of your changes." $ git push origin name-of-your-bugfix-or-feature -7. If you are editing the docs, compile and open them with:: +#. If you are editing the docs, compile and open them with:: $ make docs # or to simply generate the html $ cd docs/ $ make html -7. Submit a pull request through the GitHub website. +#. Submit a pull request through the GitHub website. Pull Request Guidelines ----------------------- Before you submit a pull request, check that it meets these guidelines: -1. The pull request should include tests. -2. If the pull request adds functionality, the docs should be updated. Put - your new functionality into a function with a docstring, and add the - feature to the list in README.rst. -3. The pull request should work for all major supported Python versions (3.8, 3.9, 3.10, and 3.11). +#. The pull request should include tests. + +#. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in ``README.rst``. + +#. The pull request should work for Python 3.8, 3.9, 3.10, and 3.11. Check that the tests pass for all supported Python versions. + Tips ---- @@ -128,40 +126,53 @@ To run a subset of tests:: $ pytest tests.test_figanos - Versioning/Tagging ------------------ -A reminder for the maintainers on how to deploy. -Make sure all your changes are committed (including an entry in HISTORY.rst). -Then run:: +A reminder for the maintainers on how to deploy. This section is only relevant for maintainers when they are producing a new point release for the package. + +#. Create a new branch from `main` (e.g. `release-0.2.0`). +#. Update the `CHANGES.rst` file to change the `Unreleased` section to the current date. +#. Create a pull request from your branch to `main`. +#. Once the pull request is merged, create a new release on GitHub. On the main branch, run: + + .. code-block:: shell + + $ bump-my-version bump minor # In most cases, we will be releasing a minor version + $ git push + $ git push --tags + + This will trigger the CI to build the package and upload it to TestPyPI. In order to upload to PyPI, this can be done by publishing a new version on GitHub. This will then trigger the workflow to build and upload the package to PyPI. -$ bumpversion patch # possible: major / minor / patch -$ git push -$ git push --tags +#. Once the release is published, it will go into a `staging` mode on Github Actions. Once the tests pass, admins can approve the release (an e-mail will be sent) and it will be published on PyPI. + +.. note:: + + The ``bump-version.yml`` GitHub workflow will automatically bump the patch version when pull requests are pushed to the ``main`` branch on GitHub. It is not necessary to manually bump the version in your branch when merging (non-release) pull requests. + +.. warning:: + + It is important to be aware that any changes to files found within the ``figanos`` folder (with the exception of ``figanos/__init__.py``) will trigger the ``bump-version.yml`` workflow. Be careful not to commit changes to files in this folder when preparing a new release. Packaging --------- -When a new version has been minted (features have been successfully integrated test coverage and stability is adequate), -maintainers should update the pip-installable package (wheel and source release) on PyPI as well as the binary on conda-forge. +When a new version has been minted (features have been successfully integrated test coverage and stability is adequate), maintainers should update the pip-installable package (wheel and source release) on PyPI as well as the binary on conda-forge. The simple approach ~~~~~~~~~~~~~~~~~~~ -The simplest approach to packaging for general support (pip wheels) requires the following packages installed: - * build - * setuptools - * twine - * wheel +The simplest approach to packaging for general support (pip wheels) requires that ``flit`` be installed:: + + $ python -m pip install flit From the command line on your Linux distribution, simply run the following from the clone's main dev branch:: # To build the packages (sources and wheel) - $ python -m build --sdist --wheel + $ python -m flit build # To upload to PyPI - $ twine upload dist/* + $ python -m flit publish dist/* The new version based off of the version checked out will now be available via `pip` (`$ pip install figanos`). @@ -171,19 +182,25 @@ Releasing on conda-forge Initial Release ^^^^^^^^^^^^^^^ -In order to prepare an initial release on conda-forge, we *strongly* suggest consulting the following links: +Before preparing an initial release on conda-forge, we *strongly* suggest consulting the following links: * https://conda-forge.org/docs/maintainer/adding_pkgs.html * https://github.com/conda-forge/staged-recipes +In order to create a new conda build recipe, to be used when proposing packages to the conda-forge repository, we strongly suggest using the ``grayskull`` tool:: + + $ python -m pip install grayskull + $ grayskull pypi figanos + +For more information on ``grayskull``, please see the following link: https://github.com/conda/grayskull + Before updating the main conda-forge recipe, we echo the conda-forge documentation and *strongly* suggest performing the following checks: * Ensure that dependencies and dependency versions correspond with those of the tagged version, with open or pinned versions for the `host` requirements. - * If possible, configure tests within the conda-forge build CI (e.g. `imports: figanos`, `commands: pytest figanos`) + * If possible, configure tests within the conda-forge build CI (e.g. `imports: figanos`, `commands: pytest figanos`). Subsequent releases ^^^^^^^^^^^^^^^^^^^ -If the conda-forge feedstock recipe is built from PyPI, then when a new release is published on PyPI, `regro-cf-autotick-bot` will open Pull Requests automatically on the conda-forge feedstock. -It is up to the conda-forge feedstock maintainers to verify that the package is building properly before merging the Pull Request to the main branch. +If the conda-forge feedstock recipe is built from PyPI, then when a new release is published on PyPI, `regro-cf-autotick-bot` will open Pull Requests automatically on the conda-forge feedstock. It is up to the conda-forge feedstock maintainers to verify that the package is building properly before merging the Pull Request to the main branch. Building sources for wide support with `manylinux` image ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -192,8 +209,7 @@ Building sources for wide support with `manylinux` image This section is for building source files that link to or provide links to C/C++ dependencies. It is not necessary to perform the following when building pure Python packages. -In order to do ensure best compatibility across architectures, we suggest building wheels using the `PyPA`'s `manylinux` -docker images (at time of writing, we endorse using `manylinux_2_24_x86_64`). +In order to do ensure best compatibility across architectures, we suggest building wheels using the `PyPA`'s `manylinux` docker images (at time of writing, we endorse using `manylinux_2_24_x86_64`). With `docker` installed and running, begin by pulling the image:: @@ -203,11 +219,10 @@ From the figanos source folder we can enter into the docker container, providing $ sudo docker run --rm -ti -v $(pwd):/figanos -w /figanos quay.io/pypa/manylinux_2_24_x86_64 bash -Finally, to build the wheel, we run it against the provided Python3.8 binary:: +Finally, to build the wheel, we run it against the provided Python3.9 binary:: - $ /opt/python/cp38-cp38m/bin/python setup.py sdist bdist_wheel + $ /opt/python/cp39-cp39m/bin/python -m build --sdist --wheel -This will then place two files in `figanos/dist/` ("figanos-1.2.3-py3-none-any.whl" and "figanos-1.2.3.tar.gz"). -We can now leave our docker container (`$ exit`) and continue with uploading the files to PyPI:: +This will then place two files in `figanos/dist/` ("figanos-1.2.3-py3-none-any.whl" and "figanos-1.2.3.tar.gz"). We can now leave our docker container (`$ exit`) and continue with uploading the files to PyPI:: $ twine upload dist/* diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 0bfe6d38..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,26 +0,0 @@ -include AUTHORS.rst -include CONTRIBUTING.rst -include HISTORY.rst -include LICENSE -include README.rst -include .zenodo.json -include requirements_dev.txt -include requirements_docs.txt - -recursive-include figanos *.json *.mplstyle *.py *.txt -recursive-include docs *.rst conf.py Makefile make.bat *.jpg *.png *.gif -recursive-include figanos/data *.json *.png *.txt *.yml - -recursive-exclude * __pycache__ -recursive-exclude * *.py[co] - -exclude .coveralls.yml -exclude .cruft.json -exclude .editorconfig -exclude .pre-commit-config.yaml -exclude .readthedocs.yml -exclude .yamllint.yaml -exclude Makefile -exclude environment.yml -exclude environment-docs.yml -exclude tox.ini diff --git a/Makefile b/Makefile index b77edbc1..756536b3 100644 --- a/Makefile +++ b/Makefile @@ -53,15 +53,18 @@ clean-test: ## remove test and coverage artifacts rm -fr .pytest_cache lint/flake8: ## check style with flake8 - flake8 figanos tests + ruff figanos tests + flake8 --config=.flake8 figanos tests lint/black: ## check style with black black --check figanos tests + blackdoc --check figanos docs + isort --check figanos tests lint: lint/flake8 lint/black ## check style test: ## run tests quickly with the default Python - pytest + python -m pytest test-all: ## run tests on every Python version with tox tox @@ -87,13 +90,15 @@ endif servedocs: docs ## compile the docs watching for changes watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D . -release: dist ## package and upload a release - twine upload dist/* - dist: clean ## builds source and wheel package - python -m build --sdist - python -m build --wheel + python -m flit build ls -l dist +release: dist ## package and upload a release + python -m flit publish dist/* + install: clean ## install the package to the active Python's site-packages - python setup.py install + python -m flit install + +dev: clean ## install the package to the active Python's site-packages + python -m flit install --symlink diff --git a/README.rst b/README.rst index f18e7e1a..6061f81b 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,6 @@ figanos ======= - .. image:: https://img.shields.io/pypi/v/figanos.svg :target: https://pypi.python.org/pypi/figanos :alt: PyPI @@ -21,10 +20,7 @@ figanos Figanos: Tool to create FIGures in the OurANOS style - -Pour nous partager vos codes à ajouter dans figanos, s.v.p créer un issue sur le repo github avec une description de la fonction et -le code de celle-ci. - +Pour nous partager vos codes à ajouter dans figanos, s.v.p créer un issue sur le repo github avec une description de la fonction et le code de celle-ci. * Free software: Apache Software License 2.0 * Documentation: https://figanos.readthedocs.io. diff --git a/docs/changes.rst b/docs/changes.rst new file mode 100644 index 00000000..d9e113ec --- /dev/null +++ b/docs/changes.rst @@ -0,0 +1 @@ +.. include:: ../CHANGES.rst diff --git a/docs/history.rst b/docs/history.rst deleted file mode 100644 index 25064996..00000000 --- a/docs/history.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../HISTORY.rst diff --git a/docs/index.rst b/docs/index.rst index 8c7a259b..db5c3dd3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -21,7 +21,7 @@ Need help? api contributing authors - history + changes .. toctree:: :maxdepth: 1 diff --git a/docs/installation.rst b/docs/installation.rst index dde5c32d..8de7b42e 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -10,7 +10,7 @@ To install figanos, run these commands in your terminal: .. code-block:: console $ mamba install -c conda-forge gdal - $ pip install figanos + $ python -m pip install figanos Development Installation (conda + pip) -------------------------------------- @@ -28,12 +28,14 @@ Then you can create the environment and install the package: .. code-block:: console $ cd figanos - $ conda env create -f environment.yml + $ conda env create -f environment-dev.yml -Finally, perform an `--editable` install of figanos: +Finally, perform an `--symlink` install of figanos: .. code-block:: console - $ pip install -e . + $ flit install --symlink + # Or + $ make dev .. _Github repo: https://github.com/Ouranosinc/figanos diff --git a/environment.yml b/environment-dev.yml similarity index 84% rename from environment.yml rename to environment-dev.yml index 397f2d0d..220a2e6e 100644 --- a/environment.yml +++ b/environment-dev.yml @@ -27,9 +27,9 @@ dependencies: - holoviews # Development - black - - bump2version - - coverage - - coveralls + - bump-my-version >=0.12.0 + - coverage >=6.2,<7.0 + - coveralls >=3.3.1 - flake8 - isort - pip @@ -45,10 +45,9 @@ dependencies: - nbsphinx - notebook - pandoc - - sphinx + - sphinx >=6.2.0 - sphinx-autoapi - - sphinx-book-theme - - sphinx-click + - sphinx-book-theme >=1.0.0 - sphinx-codeautolink - sphinx-copybutton - sphinxcontrib-napoleon diff --git a/figanos/__init__.py b/figanos/__init__.py index 6b4ed4f3..693ae7d6 100644 --- a/figanos/__init__.py +++ b/figanos/__init__.py @@ -1,4 +1,4 @@ -"""Top-level package for figanos.""" +"""Outils pour produire des graphiques informatifs sur les impacts des changements climatiques.""" __author__ = """Sarah-Claude Bourdeau-Goulet""" __email__ = "bourdeau-goulet.sarah-claude@ouranos.ca" diff --git a/figanos/_logo.py b/figanos/_logo.py index 9c356774..9b8c9773 100644 --- a/figanos/_logo.py +++ b/figanos/_logo.py @@ -1,10 +1,11 @@ +from __future__ import annotations + import logging import shutil import urllib.parse import urllib.request import warnings from pathlib import Path -from typing import Optional, Union import platformdirs import yaml @@ -56,10 +57,10 @@ class Logos: def __init__(self) -> None: """Initialize the Logo class instance.""" - self._config = None - self._catalogue = None - self._default = None - self._logos = {} + self._config: Path = Path(platformdirs.user_config_dir("figanos")) / "logos" + self._catalogue: Path = self._config / LOGO_CONFIG_FILE + self._default: Path = self._config / "figanos_logo.png" + self._logos: dict[str, str] = {} self.reload_config() if not self._logos.get("default"): @@ -67,30 +68,18 @@ def __init__(self) -> None: self.set_logo(_figanos_logo) self.set_logo(_figanos_logo, name="default") - @property - def config(self) -> Path: - """The path to the logo configuration folder.""" - if self._config is None: - self._config = ( - Path(platformdirs.user_config_dir("figanos", ensure_exists=True)) - / "logos" - ) - return self._config - @property def catalogue(self) -> Path: """The path to the logo configuration file.""" - if self._catalogue is None: - self._catalogue = self.config / LOGO_CONFIG_FILE return self._catalogue @property - def default(self) -> str: + def default(self) -> Path: """The path to the default logo.""" return self._default @default.setter - def default(self, value: Union[str, Path]): + def default(self, value: Path): """Set a default logo.""" self._default = value @@ -103,7 +92,7 @@ def _setup(self) -> None: warnings.warn( f"No logo configuration file found. Creating one at {self.catalogue}." ) - self.config.mkdir(parents=True, exist_ok=True) + self._config.mkdir(parents=True, exist_ok=True) with open(self.catalogue, "w") as f: yaml.dump(dict(logos={}), f) @@ -115,13 +104,13 @@ def __repr__(self) -> str: """Return the default logo filepath.""" return f"{self._default}" - def __getitem__(self, args) -> Optional[str]: + def __getitem__(self, args) -> str | None: """Retrieve a logo filepath by its name. If it does not exist, it will be installed, with the filepath returned. """ try: - return self._logos[args] + return str(self._logos[args]) except (KeyError, TypeError): if isinstance(args, tuple): return self.set_logo(*args) @@ -141,9 +130,7 @@ def installed(self) -> list: """Retrieve a list of installed logos.""" return list(self._logos.keys()) - def set_logo( - self, path: Union[str, Path], name: Optional[str] = None - ) -> Optional[str]: + def set_logo(self, path: str | Path, name: str | None = None) -> str | None: """Copy an image at a given path to the config folder and map it to a given name in the catalogue.""" _logo_mapping = yaml.safe_load(self.catalogue.read_text())["logos"] @@ -151,7 +138,7 @@ def set_logo( if logo_path.exists() and logo_path.is_file(): if name is None: name = logo_path.stem.replace("-", "_") - install_logo_path = self.config / logo_path.name + install_logo_path = self._config / logo_path.name if not install_logo_path.exists(): shutil.copy(logo_path, install_logo_path) @@ -163,12 +150,13 @@ def set_logo( if name != "default": return self._logos[name] else: - return self._default + return str(self._default) elif not logo_path.exists(): warnings.warn(f"Logo file `{logo_path}` not found. Not setting logo.") elif not logo_path.is_file(): warnings.warn(f"Logo path `{logo_path}` is a folder. Not setting logo.") + return None def install_ouranos_logos(self, *, permitted: bool = False) -> None: """Fetch and install the Ouranos logo. @@ -184,11 +172,11 @@ def install_ouranos_logos(self, *, permitted: bool = False) -> None: for orientation in ["horizontal", "vertical"]: for colour in ["couleur", "blanc", "noir"]: file = f"logo-ouranos-{orientation}-{colour}.svg" - if not (self.config / file).exists(): + if not (self._config / file).exists(): logo_url = urllib.parse.urljoin(OURANOS_LOGOS_URL, file) try: - urllib.request.urlretrieve(logo_url, self.config / file) - self.set_logo(self.config / file) + urllib.request.urlretrieve(logo_url, self._config / file) + self.set_logo(self._config / file) except Exception as e: logging.error( f"Error downloading or setting Ouranos logo: {e}" @@ -196,12 +184,12 @@ def install_ouranos_logos(self, *, permitted: bool = False) -> None: if Path(self.default).stem == "figanos_logo": _default_ouranos_logo = ( - self.config / "logo-ouranos-horizontal-couleur.svg" + self._config / "logo-ouranos-horizontal-couleur.svg" ) warnings.warn(f"Setting default logo to {_default_ouranos_logo}.") self.set_logo(_default_ouranos_logo, name="default") self.reload_config() - print(f"Ouranos logos installed at: {self.config}.") + print(f"Ouranos logos installed at: {self._config}.") else: warnings.warn( "You have not indicated that you have permission to use the Ouranos logo. " diff --git a/figanos/matplotlib/utils.py b/figanos/matplotlib/utils.py index 34a83df7..1b5508a6 100644 --- a/figanos/matplotlib/utils.py +++ b/figanos/matplotlib/utils.py @@ -75,10 +75,10 @@ def get_localized_term(term, locale=None): return TERMS[term][locale] -def empty_dict(param): +def empty_dict(param) -> dict: """Return empty dict if input is None.""" if param is None: - param = {} + param = dict() return param @@ -175,7 +175,7 @@ def get_array_categ(array: xr.DataArray | xr.Dataset) -> str: def get_attributes( - string: str, xr_obj: xr.DataArray | xr.Dataset, locale: str = None + string: str, xr_obj: xr.DataArray | xr.Dataset, locale: str | None = None ) -> str: """Fetch attributes or dims corresponding to keys from Xarray objects. @@ -360,8 +360,8 @@ def sort_lines(array_dict: dict[str, Any]) -> dict[str, str]: def loc_mpl( - loc: str | tuple[float, float] | int, -) -> tuple[tuple[float, float], tuple[float, float], str, str]: + loc: str | tuple[int | float, int | float] | int, +) -> tuple[tuple[float, float], tuple[int | float, int | float], str, str]: """Find coordinates and alignment associated to loc string. Parameters @@ -574,11 +574,11 @@ def load_image( The scaled image. """ if pathlib.Path(im).suffix == ".png": - im = mpl.pyplot.imread(im) - original_height, original_width = im.shape[:2] + image = mpl.pyplot.imread(im) + original_height, original_width = image.shape[:2] if height is None and width is None: - return im + return image warnings.warn( "The scikit-image library is used to resize PNG images. This may affect logo image quality." @@ -596,7 +596,7 @@ def load_image( # Only height is provided, derive zoom factor for width based on aspect ratio width = (height / original_height) * original_width - return resize(im, (height, width, im.shape[2]), anti_aliasing=True) + return resize(image, (height, width, image.shape[2]), anti_aliasing=True) elif pathlib.Path(im).suffix == ".svg": cairo_kwargs = dict(url=im) @@ -779,7 +779,7 @@ def fill_between_label( def get_var_group( path_to_json: str | pathlib.Path, da: xr.DataArray | None = None, - unique_str: str = None, + unique_str: str | None = None, ) -> str: """Get IPCC variable group from DataArray or a string using a json file (figanos/data/ipcc_colors/variable_groups.json). @@ -1047,7 +1047,7 @@ def get_mpl_styles() -> dict[str, str]: folder = pathlib.Path(__file__).parent / "style/" paths = sorted(folder.glob("*.mplstyle")) names = [str(p).split("/")[-1].removesuffix(".mplstyle") for p in paths] - styles = {name: path for name, path in zip(names, paths)} + styles = {str(name): path for name, path in zip(names, paths)} return styles diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..405fdb69 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,258 @@ +[build-system] +requires = ["flit_core >=3.8,<4"] +build-backend = "flit_core.buildapi" + +[project] +name = "figanos" +authors = [ + {name = "Sarah-Claude Bourdeau-Goulet", email = "bourdeau-goulet.sarah-claude@ouranos.ca"}, + {name = "Juliette Lavoie", email = "lavoie.juliette@ouranos.ca"}, + {name = "Alexis Beaupré-Laperrière", email = "Beaupre-Laperriere.Alexis@ouranos.ca"} +] +maintainers = [ + {name = "Sarah-Claude Bourdeau-Goulet", email = "bourdeau-goulet.sarah-claude@ouranos.ca"}, + {name = "Juliette Lavoie", email = "lavoie.juliette@ouranos.ca"}, + {name = "Trevor James Smith", email = "smith.trevorj@ouranos.ca"} +] +readme = {file = "README.rst", content-type = "text/x-rst"} +requires-python = ">=3.8.0" +keywords = ["figanos"] +license = {file = "LICENSE"} +classifiers = [ + "Development Status :: 2 - Pre-Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation :: CPython" +] +dynamic = ["description", "version"] +dependencies = [ + "cartopy", + "cairosvg", + "geopandas", + "matplotlib", + "numpy", + "pandas", + "platformdirs", + "pyyaml", + "seaborn", + "scikit-image", + "xarray", + "xclim>=0.38" +] + +[project.optional-dependencies] +dev = [ + # Dev tools and testing + "pip>=23.3", + "bump-my-version>=0.12.0", + "watchdog>=3.0.0", + "flake8>=6.1.0", + "flake8-rst-docstrings>=0.3.0", + "flit", + "tox>=4.5.1", + "coverage>=6.2.2,<7.0.0", + "coveralls>=3.3.1", + "pytest>=7.3.1", + "pytest-cov>=4.0.0", + "black>=23.11.0", + "blackdoc>=0.3.9", + "isort>=5.12.0", + "pre-commit>=3.3.2" +] +docs = [ + # Documentation and examples + "dask", + "h5py", + "netcdf4", + "zarr", + "geoviews", + "holoviews", + "ipykernel", + "ipython", + "jupyter_client", + "nbsphinx", + "sphinx-codeautolink", + "sphinx-copybutton", + "sphinx>=6.2.0", + "sphinx-book-theme>=1.0", + "sphinxcontrib-napoleon" +] + +[project.urls] +"Homepage" = "https://figanos.readthedocs.io/" +"Changelog" = "https://figanos.readthedocs.io/en/stable/changes.html" +"Issue tracker" = "https://github.com/Ouranosinc/figanos/issues" +"Source" = "https://github.com/Ouranosinc/figanos" +"About Ouranos" = "https://www.ouranos.ca/en/" + +[tool] + +[tool.black] +target-version = [ + "py38", + "py39", + "py310", + "py311" +] + +[tool.bumpversion] +current_version = "0.2.0" +commit = true +tag = true +tag_name = "{new_version}" +allow_dirty = false +serialize = ["{major}.{minor}.{patch}"] +parse = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)" + +[[tool.bumpversion.files]] +filename = "figanos/__init__.py" +search = "__version__ = \"{current_version}\"" +replace = "__version__ = \"{new_version}\"" + +[[tool.bumpversion.files]] +filename = "tests/test_figanos.py" +search = "__version__ = \"{current_version}\"" +replace = "__version__ = \"{new_version}\"" + +[[tool.bumpversion.files]] +filename = ".cruft.json" +search = "\"version\": \"{current_version}\"" +replace = "\"version\": \"{new_version}\"" + +[tool.coverage.run] +relative_files = true +include = ["figanos/*"] +omit = ["tests/*.py"] + +[tool.flit.sdist] +include = [ + ".zenodo.json", + "AUTHORS.rst", + "CHANGES.rst", + "CONTRIBUTING.rst", + "LICENSE", + "Makefile", + "README.rst", + "docs/*.rst", + "docs/Makefile", + "docs/_static/_images/*.gif", + "docs/_static/_images/*.jpg", + "docs/_static/_images/*.png", + "docs/_static/_images/*.rst", + "docs/conf.py", + "docs/make.bat", + "docs/notebooks/.ipynb", + "environment-docs.yml", + "environment-dev.yml", + "tests/*.py", + "figanos", + "tox.ini" +] +exclude = [ + "*.py[co]", + "__pycache__", + ".coveralls.yml", + ".editorconfig", + ".flake8", + ".gitignore", + ".pre-commit-config.yaml", + ".readthedocs.yml", + ".yamllint.yaml", + "docs/modules.rst", + "docs/figanos*.rst" +] + +[tool.isort] +profile = "black" +py_version = 38 + +[tool.mypy] +python_version = 3.8 +show_error_codes = true +warn_return_any = true +warn_unused_configs = true + +[[tool.mypy.overrides]] +module = [ + "cairosvg.*", + "cartopy.*", + "matplotlib.*", + "mpl_toolkits.*", + "geopandas.*", + "holoviews.*", + "numpy.*", + "pandas.*", + "scipy.*", + "seaborn.*", + "skimage.transform.*", + "xarray.*", + "xclim.*", + "yaml.*" +] +ignore_missing_imports = true + +[tool.pytest.ini_options] +addopts = [ + "--verbose", + "--color=yes" +] +filterwarnings = ["ignore::UserWarning"] +testpaths = "tests" + +[tool.ruff] +src = [""] +line-length = 150 +target-version = "py38" +exclude = [ + ".eggs", + ".git", + "build", + "docs", + "tests" +] +ignore = [ + "D205", + "D400", + "D401" +] +select = [ + "C9", + "D", + "E", + "F", + "W" +] + +[tool.ruff.flake8-bandit] +check-typed-exception = true + +[tool.ruff.format] +line-ending = "auto" + +[tool.ruff.isort] +known-first-party = ["figanos"] +case-sensitive = true +detect-same-package = false +lines-after-imports = 1 +no-lines-before = ["future", "standard-library"] + +[tool.ruff.mccabe] +max-complexity = 15 + +[tool.ruff.per-file-ignores] +"figanos/**/__init__.py" = ["F401", "F403"] +"figanos/matplotlib/**/*.py" = ["C901"] + +[tool.ruff.pycodestyle] +max-doc-length = 180 + +[tool.ruff.pydocstyle] +convention = "numpy" diff --git a/requirements_dev.txt b/requirements_dev.txt deleted file mode 100644 index bccebb04..00000000 --- a/requirements_dev.txt +++ /dev/null @@ -1,15 +0,0 @@ -pip==23.3 -bump2version==1.0.1 -wheel==0.40.0 -build==0.10.0 -flake8==6.0.0 -tox==4.5.1 -coverage==7.2.5 -coveralls==3.3.1 -sphinx==7.0.1 -twine==4.0.2 -pytest==7.3.1 -pytest-cov==4.0.0 -black==23.3.0 -isort==5.12.0 -pre-commit==3.3.2 diff --git a/requirements_docs.txt b/requirements_docs.txt deleted file mode 100644 index 7e222ffc..00000000 --- a/requirements_docs.txt +++ /dev/null @@ -1,20 +0,0 @@ -xclim>=0.38 -dask -h5py -netcdf4 -pyyaml -zarr -geoviews -holoviews -ipykernel -ipython -jupyter_client -nbsphinx -pandoc -sphinx -sphinx-autoapi -sphinx-click -sphinx-codeautolink -sphinx-copybutton -sphinx_book_theme -sphinxcontrib-napoleon diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 9c112791..00000000 --- a/setup.cfg +++ /dev/null @@ -1,77 +0,0 @@ -[bumpversion] -current_version = 0.2.0 -commit = True -tag = False - -[bumpversion:file:setup.py] -search = version="{current_version}" -replace = version="{new_version}" - -[bumpversion:file:figanos/__init__.py] -search = __version__ = "{current_version}" -replace = __version__ = "{new_version}" - -[bumpversion:file:tests/test_figanos.py] -search = __version__ = "{current_version}" -replace = __version__ = "{new_version}" - -[bumpversion:file:.cruft.json] -search = "version": "{current_version}", -replace = "version": "{new_version}", - -[aliases] -test = pytest - -[tool:pytest] -collect_ignore = ['setup.py'] -addopts = - --verbose -filterwarnings = - ignore::UserWarning - -[flake8] -exclude = - .git, - docs, - build, - .eggs, - docs/conf.py, -max-line-length = 88 -max-complexity = 12 -ignore = - C901 - E203 - E231 - E266 - E501 - F401 - F403 - W503 - W504 -per-file-ignores = - tests/*:E402 -rst-roles = - mod, - py:attr, - py:attribute, - py:class, - py:const, - py:data, - py:func, - py:meth, - py:mod, - py:obj, - py:ref, - ref - -[coverage:run] -relative_files = True -omit = */tests/*.py - -[isort] -profile = black -py_version = 38 - -[pydocstyle] -convention = numpy -match = ((?!test_|conf).)*\.py diff --git a/setup.py b/setup.py deleted file mode 100644 index 3866360a..00000000 --- a/setup.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python - -"""The setup script.""" - -from setuptools import find_packages, setup - -with open("README.rst") as readme_file: - readme = readme_file.read() - -requirements = [ - "cartopy", - "cairosvg", - "geopandas", - "matplotlib", - "numpy", - "pandas", - "platformdirs", - "pyyaml", - "seaborn", - "scikit-image", - "xarray", - "xclim", -] - -docs_requirements = [ - dependency for dependency in open("requirements_docs.txt").readlines() -] - -dev_requirements = [ - dependency for dependency in open("requirements_dev.txt").readlines() -] - -setup( - author="Sarah-Claude Bourdeau-Goulet", - author_email="bourdeau-goulet.sarah-claude@ouranos.ca", - python_requires=">=3.8", - classifiers=[ - "Development Status :: 2 - Pre-Alpha", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Natural Language :: English", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - ], - description="Outils pour produire des graphiques informatifs sur les impacts des changements climatiques.", - install_requires=requirements, - license="Apache Software License 2.0", - long_description=readme, - long_description_content_type="text/x-rst", - include_package_data=True, - keywords="figanos", - name="figanos", - packages=find_packages(include=["figanos", "figanos.*"]), - test_suite="tests", - extras_require={ - "docs": docs_requirements, - "dev": dev_requirements, - }, - project_urls={ - "Source": "https://github.com/Ouranosinc/figanos", - "Issue tracker": "https://github.com/Ouranosinc/figanos/issues", - "About Ouranos": "https://www.ouranos.ca/en/", - }, - version="0.2.0", - zip_safe=False, -) diff --git a/tests/test_figanos.py b/tests/test_figanos.py index 5c533b93..05ecf941 100644 --- a/tests/test_figanos.py +++ b/tests/test_figanos.py @@ -27,7 +27,7 @@ def test_content(response): def test_package_metadata(): """Test the package metadata.""" - project = pkgutil.get_loader("figanos").get_filename() + project = pkgutil.get_loader("figanos").get_filename() # noqa metadata = pathlib.Path(project).resolve().parent.joinpath("__init__.py") diff --git a/tox.ini b/tox.ini index bd282306..0a6a3374 100644 --- a/tox.ini +++ b/tox.ini @@ -1,20 +1,24 @@ [tox] min_version = 4.0 envlist = - black + lint py{38,39,310,311} docs coveralls requires = - pip >= 21.0 + flit + pip >= 23.3.0 opts = --verbose -[testenv:black] +[testenv:lint] skip_install = True deps = - flake8 black + blackdoc + isort + flake8 + ruff commands = make lint allowlist_externals = @@ -33,6 +37,8 @@ setenv = PYTEST_ADDOPTS = "--color=yes" PYTHONPATH = {toxinidir} passenv = + CI + COVERALLS_* GITHUB_* extras = dev