diff --git a/.github/workflows/ci_codecov.yml b/.github/workflows/ci_codecov.yml index e537b8ae..81e9fcbf 100644 --- a/.github/workflows/ci_codecov.yml +++ b/.github/workflows/ci_codecov.yml @@ -21,19 +21,16 @@ on: - cron: "0 0 * * *" jobs: - run: + test: name: Test on ${{ matrix.os }}, Python ${{ matrix.python-version }} runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest] - - env: - OS: ${{ matrix.os }} - python-version: "3.7" + python-version: ["3.11"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Additional info about the build shell: bash run: | @@ -42,7 +39,7 @@ jobs: ulimit -a - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} architecture: x64 @@ -51,22 +48,27 @@ jobs: shell: bash run: | python -m pip install --upgrade pip + python -m pip install -r requirements_dev.txt + python -m pip install -U pytest pytest-cov codecov + + - name: Install package + shell: bash + run: | python -m pip install . # pip install tox tox-gh-actions - python -m pip install -r requirements.txt - python -m pip install -U pytest pytest-cov - name: Run tests shell: bash run: | - pytest --cov=./ --cov-config=.coveragerc --cov-report=xml --color=yes procrustes/test/ + python -m pytest -c pyproject.toml --cov-config=.coveragerc --cov-report=xml --color=yes selector - name: CodeCov - uses: codecov/codecov-action@v3.1.0 + uses: codecov/codecov-action@v4.5.0 with: + token: ${{ secrets.CODECOV_TOKEN }} + # Temp fix for https://github.com/codecov/codecov-action/issues/1487 + version: v0.6.0 fail_ci_if_error: true - directory: ./coverage/reports/ file: ./coverage.xml - verbose: true flags: unittests name: codecov-${{ matrix.os }}-py${{ matrix.python-version }} diff --git a/.github/workflows/ci_tox.yml b/.github/workflows/ci_tox.yml index f75230c1..7576bb06 100644 --- a/.github/workflows/ci_tox.yml +++ b/.github/workflows/ci_tox.yml @@ -1,30 +1,63 @@ name: CI Tox + on: - push: - # branches: [master, tox] - pull_request: - branches: [master] + # GitHub has started calling new repo's first branch "main" https://github.com/github/renaming + # Existing codes likely still have "master" as the primary branch + # Both are tracked here to keep legacy and new codes working + push: + branches: + - "master" + - "main" + pull_request: + branches: + - "master" + - "main" + schedule: + # Nightly tests run on master by default: + # Scheduled workflows run on the latest commit on the default or base branch. + # (from https://help.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule) + - cron: "0 0 * * *" jobs: - test: - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + test: + name: Test on ${{ matrix.os }}, Python ${{ matrix.python-version }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + # os: [macOS-latest, windows-latest, ubuntu-latest] + os: [macos-13, windows-latest, ubuntu-latest] + python-version: ["3.9", "3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + - name: Additional info about the build + shell: bash + run: | + uname -a + df -h + ulimit -a + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + architecture: x64 + + - name: Install dependencies + shell: bash + run: | + python -m pip install --upgrade pip + python -m pip install -r requirements_dev.txt + # python -m pip install -U pytest pytest-cov codecov + python -m pytest -c pyproject.toml --cov-config=.coveragerc --cov-report=xml --color=yes procrustes - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - architecture: x64 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install tox tox-gh-actions - - name: Testing with tox - run: tox + - name: Install package + shell: bash + run: | + python -m pip install . + pip install tox tox-gh-actions + - name: Run tests + shell: bash + run: | + tox diff --git a/README.md b/README.md index 9e78cab6..74ce3ea1 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,12 @@ Procrustes ========== -[![This project supports Python 3.6+](https://img.shields.io/badge/Python-3.6+-blue.svg)](https://python.org/downloads) +[![This project supports Python 3.8+](https://img.shields.io/badge/Python-3.8+-blue.svg)](https://python.org/downloads) [![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg)](https://opensource.org/licenses/) [![GitHub Actions CI Tox Status](https://github.com/theochem/procrustes/actions/workflows/ci_tox.yml/badge.svg?branch=master)](https://github.com/theochem/procrustes/actions/workflows/ci_tox.yml) [![Documentation Status](https://readthedocs.org/projects/procrustes/badge/?version=latest)](https://procrustes.readthedocs.io/en/latest/?badge=latest) [![codecov](https://codecov.io/gh/theochem/procrustes/branch/master/graph/badge.svg?token=3L96J5QQOT)](https://codecov.io/gh/theochem/procrustes) [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/theochem/procrustes/master?filepath=doc%2Fnotebooks%2F) -[![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/theochem/procrustes.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/theochem/procrustes/context:python) The Procrustes library provides a set of functions for transforming a matrix to make it as similar as possible to a target matrix. For more information, visit @@ -55,7 +54,7 @@ first, and then: ```bash # Create and activate myenv conda environment (optional, but recommended) -conda create -n myenv python=3.6 +conda create -n myenv python=3.11 conda activate myenv # Install the stable release. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..cdca03b0 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,266 @@ +# -*- coding: utf-8 -*- +# The Procrustes library provides a set of functions for transforming +# a matrix to make it as similar as possible to a target matrix. +# +# Copyright (C) 2017-2022 The QC-Devs Community +# +# This file is part of Procrustes. +# +# Procrustes is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Procrustes is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- + +[project] +name = "qc-procrustes" +description = "Python library for finding the optimal transformation(s) that makes two matrices as close as possible to each other." +readme = {file = 'README.md', content-type='text/markdown'} +requires-python = ">=3.8" +license = {file = "LICENSE"} +authors = [ + {name = "QC-Devs Community", email = "qcdevs@gmail.com"}, +] +keywords = [ + "procrustes analysis", + "statistical shape analysis", + "qudratic assignment problem", + "matrix transformation", + "generalized procrustes analysis", + "orthogonal procrustes problem", + "symmetric procrustes problem", + "rotational procrustes problem", + "permutation procrustes problem", + "softassign method", + "molecule alignment", + "chemical structure similarity", + +] + +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Natural Language :: English", + "Operating System :: MacOS", + "Operating System :: Microsoft :: Windows", + "Operating System :: Unix", + "Operating System :: POSIX", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering", + "Topic :: Scientific/Engineering :: Mathematics", + 'Topic :: Scientific/Engineering :: Physics', + 'Topic :: Scientific/Engineering :: Chemistry', + 'Intended Audience :: Science/Research', +] + +dynamic = [ + "dependencies", + "optional-dependencies", + "version", +] + +[project.scripts] +# # Command line interface entrypoint scripts +# procrustes = "procrustes.__main__:main" + +[project.urls] +homepage = "https://github.com/theochem/procrustes" +documentation = "https://procrustes.qcdevs.org/" +repository = "https://github.com/theochem/procrustes/" + +[build-system] +requires = ["setuptools>=64", "setuptools-scm>=8", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.dynamic] +dependencies = {file = ["requirements.txt"]} +optional-dependencies = {dev = { file = ["requirements_dev.txt"] }} + +[tool.setuptools_scm] +# can be empty if no extra settings are needed, presence enables setuptools-scm + +[tool.setuptools] +platforms = ["Linux", "Windows", "MacOS"] +include-package-data = true +zip-safe = true + +[tool.setuptools.package-data] +procrustes = ["*.xml"] + +[tool.setuptools.packages.find] +exclude = ["*/*/tests", "tests_*", "doc", "tools/conda.recipe", "tools/conda.recipe/*"] + +[tool.black] +line-length = 100 + +[tool.isort] +profile = "black" +known_first_party = ["procrustes"] + +[tool.ruff] +line-length = 100 +show-source = true +# Rules: https://beta.ruff.rs/docs/rules +# If you violate a rule, lookup the rule on the Rules page in ruff docs. +# Many rules have links you can click with a explanation of the rule and how to fix it. +# If there isn't a link, go to the project the rule was source from (e.g. flake8-bugbear) +# and review it's docs for the corresponding rule. +# If you're still confused, ask a fellow developer for assistance. +# You can also run "ruff rule " to explain a rule on the command line, without a browser or internet access. +select = [ + "E", # pycodestyle + "F", # Pyflakes + "W", # Warning + "B", # flake8-bugbear + "A", # flake8-builtins + "C4", # flake8-comprehensions + "T10", # flake8-debugger + "EXE", # flake8-executable, + "ISC", # flake8-implicit-str-concat + "G", # flake8-logging-format + "PIE", # flake8-pie + "T20", # flake8-print + "PT", # flake8-pytest-style + "RSE", # flake8-raise + "RET", # flake8-return + "TID", # flake8-tidy-imports + "ARG", # flake8-unused-arguments + "PGH", # pygrep-hooks + "PLC", # Pylint Convention + "PLE", # Pylint Errors + "PLW", # Pylint Warnings + "RUF", # Ruff-specific rules + + # ** Things to potentially enable in the future ** + # DTZ requires all usage of datetime module to have timezone-aware + # objects (so have a tz argument or be explicitly UTC). + # "DTZ", # flake8-datetimez + # "PTH", # flake8-use-pathlib + # "SIM", # flake8-simplify +] + +# Files to exclude from linting +extend-exclude = [ + "*.pyc", + "__pycache__", + "*.egg-info", + ".eggs", + # check point files of jupyter notebooks + "*.ipynb_checkpoints", + ".tox", + ".git", + "build", + "dist", + "docs", + "examples", + "htmlcov", + "notebooks", + ".cache", + "_version.py", +] + +# Linting error codes to ignore +ignore = [ + "F403", # unable to detect undefined names from star imports + "F405", # undefined locals from star imports + "W605", # invalid escape sequence + "A003", # shadowing python builtins + "RET505", # unnecessary 'else' after 'return' statement + "RET504", # Unnecessary variable assignment before return statement + "RET507", # Unnecessary {branch} after continue statement + "PT011", # pytest-raises-too-broad + "PT012", # pytest.raises() block should contain a single simple statement + "PLW0603", # Using the global statement to update is discouraged + "PLW2901", # for loop variable overwritten by assignment target + "G004", # Logging statement uses f-string + "PIE790", # no-unnecessary-pass + "PIE810", # multiple-starts-ends-with + "PGH003", # Use specific rule codes when ignoring type issues + "PLC1901", # compare-to-empty-string +] + +[tool.ruff.per-file-ignores] +"__init__.py" = ["F401", "E501"] +"procrustes/somefile.py" = ["E402", "E501"] +"procrustes/somedir/*" = ["E501"] + +[tool.mypy] +python_version = "3.11" +follow_imports = "skip" +ignore_missing_imports = true +files = "procrustes" +exclude = [ + "doc", + "docs", + "tools/conda.recipe", + "tools/conda.recipe/*", +] + +# Configuration for pytest +# https://docs.pytest.org/en/latest/reference/customize.html#pyproject-toml +[tool.pytest.ini_options] +addopts = [ + "--import-mode=importlib", + "--cache-clear", + "--showlocals", + "-v", + "-r a", + "--cov-report=term-missing", + "--cov=procrustes", +] +# directory containing the tests +testpaths = [ + "procrustes/tests", + "procrustes/test", +] +norecursedirs = [ + ".vscode", + "__pycache__", + "build", +] +filterwarnings = [ + "ignore::DeprecationWarning" +] +markers = [ + "slow: lower-importance tests that take an excessive amount of time", +] + +[tool.coverage.run] +omit = [ + 'procrustes/test/*', +] + +[tool.vulture] +exclude = [ + "somedir", + "*somefile.py", +] + +[tool.bandit] +exclude_dirs = [ + "procrustes/tests", + "procrustes/test", +] +skips = [ + "B101", # Ignore assert statements + "B311", # Ignore pseudo-random generators + "B404", # Ignore subprocess import + "B603", # Ignore subprocess call + "B607", # Ignore subprocess call +] diff --git a/requirements_dev.txt b/requirements_dev.txt new file mode 100644 index 00000000..a235283a --- /dev/null +++ b/requirements_dev.txt @@ -0,0 +1,4 @@ +numpy>=1.19.5 +scipy>=1.5.0 +pytest>=5.4.3 +sphinx>=2.3.0 diff --git a/setup.py b/setup.py deleted file mode 100644 index 4ee8e7de..00000000 --- a/setup.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- -# The Procrustes library provides a set of functions for transforming -# a matrix to make it as similar as possible to a target matrix. -# -# Copyright (C) 2017-2022 The QC-Devs Community -# -# This file is part of Procrustes. -# -# Procrustes is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Procrustes is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Setup and Install Script.""" - - -import os - -from setuptools import setup - - -def get_version_info(): - """Read __version__ and DEV_CLASSIFIER from version.py, using exec, not import.""" - fn_version = os.path.join("procrustes", "_version.py") - if os.path.isfile(fn_version): - myglobals = {} - with open(fn_version, "r") as f: - exec(f.read(), myglobals) # pylint: disable=exec-used - return myglobals["__version__"], myglobals["DEV_CLASSIFIER"] - return "0.0.0.post0", "Development Status :: 2 - Pre-Alpha" - - -def get_readme(): - """Load README.rst for display on PyPI.""" - with open('README.md') as fhandle: - return fhandle.read() - - -VERSION, DEV_CLASSIFIER = get_version_info() - -setup( - name="qc-procrustes", - version=VERSION, - description="Procrustes Package", - long_description=get_readme(), - long_description_content_type='text/markdown', - url="http://github.com/theochem/procrustes", - license="GNU (Version 3)", - author="QC-Devs Community", - author_email="qcdevs@gmail.com", - package_dir={"procrustes": "procrustes"}, - packages=["procrustes", "procrustes.test"], - include_package_data=True, - classifiers=[ - DEV_CLASSIFIER, - 'Environment :: Console', - 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', - 'Operating System :: POSIX :: Linux', - 'Programming Language :: Python :: 3', - 'Topic :: Scientific/Engineering :: Physics', - 'Topic :: Scientific/Engineering :: Chemistry', - 'Intended Audience :: Science/Research', - ], - install_requires=["numpy>=1.19.5", "scipy>=1.5.0", "pytest>=5.4.3", "sphinx>=2.3.0"], -)