From ea6e202ee54219b1538c2531576995a78ad0cacd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20M=C3=BCller?= Date: Thu, 27 Jun 2024 09:40:28 +0200 Subject: [PATCH] maintenance --- .github/workflows/check.yml | 40 ++++++ .github/workflows/deploy_pypi.yml | 31 +++++ .gitignore | 4 +- .readthedocs.yml | 2 +- .travis.yml | 30 ----- CHANGELOG | 4 +- multipletau/_version.py | 197 ------------------------------ pyproject.toml | 47 +++++++ setup.py | 42 ------- 9 files changed, 125 insertions(+), 272 deletions(-) create mode 100644 .github/workflows/check.yml create mode 100644 .github/workflows/deploy_pypi.yml delete mode 100644 .travis.yml delete mode 100644 multipletau/_version.py create mode 100644 pyproject.toml delete mode 100644 setup.py diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..90de6b2 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,40 @@ +name: Checks + +on: + push: + pull_request: + +jobs: + build: + + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ['3.6', '3.11'] + os: [macos-latest, ubuntu-latest, windows-latest] + extras: ['all', 'none'] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + # prerequisites + python -m pip install --upgrade pip wheel + python -m pip install coverage flake8 pytest + # show installed packages + pip freeze + - name: Install multipletau + run: | + pip install . + - name: Lint with flake8 + run: | + flake8 --exclude _version.py . + - name: Test with pytest + run: | + coverage run --source=multipletau -m pytest tests + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 diff --git a/.github/workflows/deploy_pypi.yml b/.github/workflows/deploy_pypi.yml new file mode 100644 index 0000000..1ae8619 --- /dev/null +++ b/.github/workflows/deploy_pypi.yml @@ -0,0 +1,31 @@ +name: Release to PyPI + +on: + push: + tags: + - '*' + +jobs: + deploy: + name: Deploy package to PYPI + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.10'] + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Run build + run: pipx run build --sdist --wheel + - name: publish + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_PWD }} + run: | + pipx install twine + twine upload --skip-existing dist/* diff --git a/.gitignore b/.gitignore index fd3bf40..8e1e196 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,6 @@ docs/_build .cache .eggs .env -_version_save.py +_version.py + +.idea \ No newline at end of file diff --git a/.readthedocs.yml b/.readthedocs.yml index c23c673..cadc811 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -4,4 +4,4 @@ requirements_file: docs/requirements.txt build: image: latest python: - version: 3.6 + version: 3.10 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b785589..0000000 --- a/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -notifications: - email: false -language: python -python: -- '2.7' -- '3.4' -- '3.5' -- '3.6' -install: -- travis_retry pip install -e . -- travis_retry pip install flake8 -- travis_retry pip install coverage codecov -- pip freeze -script: -- coverage run --source=multipletau setup.py test -- coverage report -m -- codecov -- flake8 multipletau -- flake8 examples -- flake8 tests -deploy: - provider: pypi - user: "ci_fcs" - password: - secure: "Jy2l/O7RqtekxbkKEwpj0S188WzcfXnzpOCKZNPu9FUpwxFlY52/IcAJoU4i8v4H00u+sv0qo4tNl4zei4yPVMAjQmW8eQv+6uusfjnrvyTve+wsCeos7tWDfD+vi/YO+k++hIdS8hK+OyrUwce/nBynANXE3vixw27ge2X2JTQ=" - on: - tags: true - distributions: "sdist bdist_wheel" - skip_cleanup: true - skip_existing: true diff --git a/CHANGELOG b/CHANGELOG index cc8ee3c..69f458d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,6 @@ -0.3.4 +0.4.0 + - setup: migrate to GitHub Actions + - setup: migrate to pyproject.toml - docs: remove dependency on old mock standalone library (#19) 0.3.3 - fix: add constant `ZERO_CUTOFF` that defines when a trace average is diff --git a/multipletau/_version.py b/multipletau/_version.py deleted file mode 100644 index dcae2da..0000000 --- a/multipletau/_version.py +++ /dev/null @@ -1,197 +0,0 @@ -#!/usr/bin/env python -"""Determine package version from git repository tag - -Each time this file is imported it checks whether the package version -can be determined using `git describe`. If this fails (because either -this file is not located at the 1st level down the repository root or -it is not under version control), the version is read from the script -"_version_save.py" which is not versioned by git, but always included -in the final distribution archive (e.g. via PyPI). If the git version -does not match the saved version, then "_version_save.py" is updated. - - -Usage ------ -1. Put this file in your main module directory: - - REPO_ROOT/package_name/_version.py - -2. Add this line to REPO_ROOT/package_name/__init__.py - - from ._version import version as __version__ # noqa: F401 - -3. (Optional) Add this line to REPO_ROOT/.gitignore - - _version_save.py - -Features --------- -- supports Python 2 and 3 -- supports frozen applications (e.g. PyInstaller) -- supports installing into a virtual environment that is located in - a git repository -- saved version is located in a python file and therefore no other - files (e.g. MANIFEST.in) need be edited -- fallback version is the creation date -- excluded from code coverage via "pragma: no cover" - -Changelog ---------- -2019-11-06.2 - - use os.path.split instead of counting os.path.sep (Windows) -2019-11-06 - - remove deprecated imp dependency (replace with parser) - - check whether this file is versioned and its location is correct - - code cleanup and docs update -""" -from __future__ import print_function - -# Put the entire script into a `True` statement and add the hint -# `pragma: no cover` to ignore code coverage here. -if True: # pragma: no cover - import os - from os.path import abspath, basename, dirname, join, split - import subprocess - import sys - import time - import traceback - import warnings - - def git_describe(): - """ - Return a string describing the version returned by the - command `git describe --tags HEAD`. - If it is not possible to determine the correct version, - then an empty string is returned. - """ - # Make sure we are in a directory that belongs to the correct - # repository. - ourdir = dirname(abspath(__file__)) - - def _minimal_ext_cmd(cmd): - # Construct minimal environment - env = {} - for k in ['SYSTEMROOT', 'PATH']: - v = os.environ.get(k) - if v is not None: - env[k] = v - # LANGUAGE is used on win32 - env['LANGUAGE'] = 'C' - env['LANG'] = 'C' - env['LC_ALL'] = 'C' - pop = subprocess.Popen(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env=env) - out = pop.communicate()[0] - return out.strip().decode('ascii', errors="ignore") - - # change directory - olddir = abspath(os.curdir) - os.chdir(ourdir) - - # Make sure that we are getting "git describe" from our own - # repository (and not from a repository where we just happen - # to be in the directory tree). - git_revision = "" - try: - # If this file is not under version control, "loc" will - # be empty. - loc = _minimal_ext_cmd(['git', 'ls-files', '--full-name', - __file__]) - # If it is under version control, it should be located - # one hierarchy down from the repository root (either - # __file__ is "docs/conf.py" or "package_name/_version.py". - if len(split(loc)) == 2: - try: - git_revision = _minimal_ext_cmd(['git', 'describe', - '--tags', 'HEAD']) - except OSError: - pass - except OSError: - pass - # Go back to original directory - os.chdir(olddir) - - return git_revision - - def load_version(versionfile): - """load version from version_save.py""" - longversion = "" - try: - with open(versionfile, "r") as fd: - data = fd.readlines() - for line in data: - if line.startswith("longversion"): - longversion = line.split("=")[1].strip().strip("'") - except BaseException: - try: - from ._version_save import longversion - except BaseException: - try: - from _version_save import longversion - except BaseException: - pass - - return longversion - - def write_version(version, versionfile): - """save version to version_save.py""" - data = "#!/usr/bin/env python\n" \ - + "# This file was created automatically\n" \ - + "longversion = '{VERSION}'\n" - try: - with open(versionfile, "w") as fd: - fd.write(data.format(VERSION=version)) - except BaseException: - if not os.path.exists(versionfile): - # Only issue a warning if the file does not exist. - msg = "Could not write package version to {}.".format( - versionfile) - warnings.warn(msg) - - hdir = dirname(abspath(__file__)) - if basename(__file__) == "conf.py" and "name" in locals(): - # This script is executed in conf.py from the docs directory - versionfile = join(join(join(hdir, ".."), - name), # noqa: F821 - "_version_save.py") - else: - # This script is imported as a module - versionfile = join(hdir, "_version_save.py") - - # Determine the accurate version - longversion = "" - - # 1. git describe - try: - # Get the version using `git describe` - longversion = git_describe() - except BaseException: - pass - - # 2. previously created version file - if longversion == "": - # Either this is not a git repository or we are in the - # wrong git repository. - # Get the version from the previously generated `_version_save.py` - longversion = load_version(versionfile) - - # 3. last resort: date - if longversion == "": - print("Could not determine version. Reason:") - print(traceback.format_exc()) - ctime = os.stat(__file__)[8] - longversion = time.strftime("%Y.%m.%d-%H-%M-%S", time.gmtime(ctime)) - print("Using creation time as version: {}".format(longversion)) - - if not hasattr(sys, 'frozen'): - # Save the version to `_version_save.py` to allow distribution using - # `python setup.py sdist`. - # This is only done if the program is not frozen (with e.g. - # pyinstaller), - if longversion != load_version(versionfile): - write_version(longversion, versionfile) - - # PEP 440-conform development version: - version = ".post".join(longversion.split("-")[:2]) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..1226162 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,47 @@ +[build-system] +requires = [ + # for version management + "setuptools>=45", "setuptools_scm[toml]>=6.2" +] +build-backend = "setuptools.build_meta" + +[project] +name = "multipletau" +authors = [ + # In alphabetical order. + {name = "André Scholich"}, + {name = "Alexandre Detiste"}, + {name = "Chris Lamb"}, + {name = "Pascal Hebbeker"}, + {name = "Paul Müller"}, +] +maintainers = [ + {name = "Paul Müller", email="dev@craban.de"}, +] +description = "A multiple-tau algorithm for Python/NumPy" +readme = "README.rst" +requires-python = ">=3.6, <4" +keywords = ["multiple tau", + "fluorescence correlation spectroscopy"] +classifiers = [ + 'Operating System :: OS Independent', + 'Programming Language :: Python :: 3', + 'Topic :: Scientific/Engineering :: Visualization', + 'Intended Audience :: Science/Research', +] +license = {text = "BSD (3 clause)"} +dependencies = [ + "numpy>=1.5.1", + ] +dynamic = ["version"] + +[project.urls] +source = "https://github.com/FCS-analysis/multipletau" +tracker = "https://github.com/FCS-analysis/multipletau/issues" +documentation = "https://multipletau.readthedocs.io/en/stable/" +changelog = "https://multipletau.readthedocs.io/en/stable/sec_changelog.html" + + +[tool.setuptools_scm] +write_to = "src/multipletau/_version.py" +version_scheme = "post-release" diff --git a/setup.py b/setup.py deleted file mode 100644 index df7b717..0000000 --- a/setup.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -from os.path import exists, dirname, realpath -from setuptools import setup -import sys - - -author = u"Paul Müller" -authors = [author] -description = 'A multiple-tau algorithm for Python/NumPy' -name = 'multipletau' -year = "2012" - -sys.path.insert(0, realpath(dirname(__file__))+"/"+name) -from _version import version - - -setup( - name=name, - author=author, - author_email='dev@craban.de', - url='https://github.com/FCS-analysis/multipletau', - version=version, - packages=[name], - package_dir={name: name}, - license="BSD (3 clause)", - description=description, - long_description=open('README.rst').read() if exists('README.rst') else '', - install_requires=["numpy >= 1.5.1"], - keywords=["multiple tau", "fluorescence correlation spectroscopy"], - setup_requires=['pytest-runner'], - tests_require=["pytest"], - classifiers= [ - 'Operating System :: OS Independent', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 3', - 'Topic :: Scientific/Engineering :: Visualization', - 'Intended Audience :: Science/Research' - ], - platforms=['ALL'] - ) -