diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 454044e75..674103893 100755 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -16,7 +16,8 @@ A few sentences and/or a bulleted list to describe and motivate the change: - [ ] docstring updated (if appropriate), - [ ] update user guide (if appropriate), - [ ] added tests, -- [ ] added line to CHANGELOG.rst, +- [ ] add a changelog entry in the `upcoming_changes` folder (see [`upcoming_changes/README.rst`](https://github.com/lumispy/lumispy/blob/main/upcoming_changes/README.rst)), +- [ ] Check formatting of the changelog entry (and eventual user guide changes) in the `docs/readthedocs.org:lumispy` build of this PR (link in github checks), - [ ] ready for review. ### Minimal example of the bug fix or the new feature diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 707d88e3c..c55223696 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -21,7 +21,7 @@ jobs: - name: Install build docs shell: bash -l {0} run: | - pip install .[build-doc] + pip install .[doc] # Add sphinx warnings as PR comments - uses: sphinx-doc/sphinx-problem-matcher@master diff --git a/.github/workflows/package_and_test.yml b/.github/workflows/package_and_test.yml new file mode 100644 index 000000000..5b2de989f --- /dev/null +++ b/.github/workflows/package_and_test.yml @@ -0,0 +1,10 @@ +name: Package & Test + +on: [push, pull_request] + +jobs: + package_and_test: + # Use the "reusable workflow" from the hyperspy organisation + uses: hyperspy/.github/.github/workflows/package_and_test.yml@main + with: + ORGANISATION: lumispy diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index db380e84b..0a97dc037 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,9 @@ name: Release +# Reusable workflows are not supported with trusted publisher +# https://github.com/pypa/gh-action-pypi-publish/issues/166 +# copy and paste "jobs" from +# https://github.com/hyperspy/.github/blob/main/.github/workflows/release_pure_python.yml + # This workflow builds the wheels "on tag". # If run from the lumispy/lumispy repository, the wheels will be uploaded to pypi ; # otherwise, the wheels will be available as a github artefact. @@ -11,82 +16,45 @@ on: - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 jobs: - create_release: + package_and_test: + name: Package and Test + # Use the "reusable workflow" from the hyperspy organisation + uses: hyperspy/.github/.github/workflows/package_and_test.yml@main + with: + ORGANISATION: lumispy + + upload_to_pypi: + needs: [package_and_test] + runs-on: ubuntu-latest + environment: release + name: Upload to pypi + permissions: + # IMPORTANT: this permission is mandatory for trusted publishing + id-token: write + steps: + - name: Download dist + uses: actions/download-artifact@v4 + + - name: Display downloaded files + run: | + ls -shR + working-directory: dist + + - uses: pypa/gh-action-pypi-publish@release/v1 + if: ${{ startsWith(github.ref, 'refs/tags/') && github.repository_owner == 'lumispy' }} + # See https://docs.pypi.org/trusted-publishers/using-a-publisher/ + + create_github_release: + # If zenodo is set up to create a DOI automatically on a GitHub release, + # this step will trigger the mining of the DOI + needs: upload_to_pypi permissions: contents: write - name: Create Release + name: Create GitHub Release runs-on: ubuntu-latest - outputs: - upload_url: ${{ steps.create_release.outputs.upload_url }} - VERSION: ${{ env.VERSION }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Create Release - id: create_release - uses: softprops/action-gh-release@3198ee18f814cdf787321b4a32a26ddbf37acc52 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions - with: - draft: false - prerelease: false - - name: Get version (on tag) - id: get_version - if: startsWith(github.ref, 'refs/tags/') - run: | - echo "VERSION=${GITHUB_REF#refs/*/v}" >> $GITHUB_ENV - echo "SETUP_VERSION=$(python setup.py --version)" >> $GITHUB_ENV - - name: Check version - if: ${{env.VERSION != env.SETUP_VERSION}} - run: | - echo "Version mismatch between pushed tag ($VERSION) and `release_info.py` ($SETUP_VERSION)" - exit 1 - - build_wheels_linux: - name: Wheels on ubuntu-latest - needs: create_release - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: 3.11 - - - name: Install release dependencies - run: | - python -m pip install twine wheel - - - name: Build source distribution - run: | - python setup.py sdist bdist_wheel - - - name: Display content dist folder - run: | - ls dist/ - - - name: Install and test distribution - env: - MPLBACKEND: agg - run: | - pip install --pre --find-links dist lumispy[tests] - pytest --pyargs lumispy - - - uses: actions/upload-artifact@v4 - with: - path: | - ./dist/*.whl - ./sdist/*.tar.gz - - - name: Publish wheels to PyPI - if: github.repository_owner == 'lumispy' - env: - # Github secret set in the lumispy/lumispy repository - # Not available from fork or pull request - # Secrets are not passed to workflows that are triggered by a pull request from a fork - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} - run: | - twine upload dist/*.whl --verbose - twine upload dist/*.tar.gz --verbose + if: ${{ startsWith(github.ref, 'refs/tags/') && github.repository_owner == 'lumispy' }} + uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 730b6e04c..0a4824c33 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -10,19 +10,22 @@ build: os: ubuntu-22.04 tools: python: "3.11" + jobs: + post_checkout: + - git fetch --unshallow || true -## Build documentation in the docs/ directory with Sphinx +# Build documentation in the docs/ directory with Sphinx sphinx: configuration: doc/conf.py # Optionally build your docs in additional formats such as PDF and ePub -formats: all - +formats: + - htmlzip python: - install: - - method: pip - path: . - extra_requirements: - - build-doc + install: + - method: pip + path: . + extra_requirements: + - doc diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 24a68108d..1b3cffd35 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,13 +6,14 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `_, and this project adheres to `Semantic Versioning `_. -UNRELEASED -========== -Changed -------- +Changelog entries for the development version are available at +https://lumispy.readthedocs.io/en/latest/changelog.html + + +.. towncrier-draft-entries:: |release| [UNRELEASED] + +.. towncrier release notes start -Maintenance ------------ - Fix intersphinx links to documentation of HyperSpy 2.0 and add linkchecker workflow - Align supported python versions (3.8-3.12) to HyperSpy 2.0 diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 9916e86b6..000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -include INSTALLATION.md -recursive-include doc *.svg diff --git a/conda_environment_dev.yml b/conda_environment_dev.yml index 2667ee783..ddbcdf64a 100644 --- a/conda_environment_dev.yml +++ b/conda_environment_dev.yml @@ -7,4 +7,6 @@ dependencies: - pytest-cov - pytest-faulthandler - pytest-xdist +- hyperspy-base +- setuptools-scm diff --git a/doc/conf.py b/doc/conf.py index a8a1f6a58..3cf369ae0 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -3,18 +3,25 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. import sys +from datetime import datetime +from importlib.metadata import version as get_version sys.path.append("../") # -- Project information -from lumispy import release_info - project = "LumiSpy" -version = release_info.version -release = release_info.version -author = release_info.author -copyright = release_info.copyright +copyright = f"2019-{datetime.today().year}, The LumiSpy developers" +author = "The LumiSpy developers" + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The full version, including alpha/beta/rc tags. +release = get_version("lumispy") +# The short X.Y version. +version = ".".join(release.split(".")[:2]) # -- General configuration @@ -27,6 +34,7 @@ "sphinx.ext.mathjax", "sphinx.ext.graphviz", "sphinx.ext.autosummary", + "sphinxcontrib.towncrier", "sphinx_copybutton", ] @@ -109,3 +117,11 @@ def setup(app): app.connect("builder-inited", run_apidoc) app.add_css_file("css/dark.css") app.add_css_file("css/light.css") + + +# -- Options for towncrier_draft extension ----------------------------------- + +# Options: draft/sphinx-version/sphinx-release +towncrier_draft_autoversion_mode = "draft" +towncrier_draft_include_empty = False +towncrier_draft_working_directory = ".." diff --git a/lumispy/__init__.py b/lumispy/__init__.py index ad5ce7999..495b83720 100644 --- a/lumispy/__init__.py +++ b/lumispy/__init__.py @@ -17,31 +17,45 @@ # along with LumiSpy. If not, see . -import logging - -_logger = logging.getLogger(__name__) +from importlib.metadata import version +from pathlib import Path from lumispy.utils.axes import nm2eV, eV2nm, nm2invcm, invcm2nm, join_spectra from lumispy.utils.io import to_array, savetxt +from lumispy import signals, components, utils + +__version__ = version("lumispy") + +# For development version, `setuptools_scm` will be used at build time +# to get the dev version, in case of missing vcs information (git archive, +# shallow repository), the fallback version defined in pyproject.toml will +# be used -from lumispy import signals -from lumispy import components -from lumispy import utils +# If we have an editable installed from a git repository try to use +# `setuptools_scm` to find a more accurate version: +# `importlib.metadata` will provide the version at installation +# time and for editable version this may be different -from . import release_info +# we only do that if we have enough git history, e.g. not shallow checkout +_root = Path(__file__).resolve().parents[1] +if (_root / ".git").exists() and not (_root / ".git/shallow").exists(): + try: + # setuptools_scm may not be installed + from setuptools_scm import get_version + + __version__ = get_version(_root) + except ImportError: # pragma: no cover + # setuptools_scm not install, we keep the existing __version__ + pass __all__ = [ + "__version__", "components", "signals", "utils", ] -__version__ = release_info.version -__author__ = release_info.author -__copyright__ = release_info.copyright -__credits__ = release_info.credits -__license__ = release_info.license -__maintainer__ = release_info.maintainer -__email__ = release_info.email -__status__ = release_info.status + +def __dir__(): + return sorted(__all__) diff --git a/lumispy/release_info.py b/lumispy/release_info.py deleted file mode 100644 index bcf329e70..000000000 --- a/lumispy/release_info.py +++ /dev/null @@ -1,43 +0,0 @@ -name = "lumispy" -version = "0.2.3dev" -description = "Analysis of luminescence spectroscopy data with HyperSpy." -author = "The LumiSpy developers" -copyright = "Copyright 2019-2023, LumiSpy developers" -credits = ["The LumiSpy developers"] -url = "https://lumispy.org" -license = "GPLv3" -platforms = ["Linux", "Mac OSX", "Windows XP/2000/NT", "Windows 95/98/ME"] -maintainer = "Jordi Ferrer Orri, Jonas Lähnemann, Duncan Johnstone, Eric Prestat" -email = "jf631@cam.ac.uk" -status = "Development" - -keywords = [ - "CL", - "PL", - "EL", - "TRCL", - "TRPL", - "SEM", - "STEM", - "TEM", - "cathodoluminescence", - "photoluminescence", - "electroluminescence", - "Raman", - "curve fitting", - "electron microscopy", - "hyperspectral", - "hyperspectrum", - "hyperspy", - "luminescence spectroscopy", - "lumispy", - "machine learning", - "model", - "multidimensional", - "numpy", - "python", - "scipy", - "spectroscopy", - "spectrum image", - "time-resolved", -] diff --git a/lumispy/signals/cl_spectrum.py b/lumispy/signals/cl_spectrum.py index b5944ad20..c6244ac67 100644 --- a/lumispy/signals/cl_spectrum.py +++ b/lumispy/signals/cl_spectrum.py @@ -77,7 +77,7 @@ def remove_spikes( add_noise=False, navigation_mask=None, interactive=False, - **kwargs + **kwargs, ): if luminescence_roi is not None and signal_mask is not None: raise AttributeError( @@ -102,7 +102,7 @@ def remove_spikes( threshold=threshold, interactive=interactive, add_noise=add_noise, - **kwargs + **kwargs, ) if threshold == "auto": diff --git a/lumispy/tests/utils/test_signals.py b/lumispy/tests/utils/test_signals.py index 53f021bae..0ab0606df 100644 --- a/lumispy/tests/utils/test_signals.py +++ b/lumispy/tests/utils/test_signals.py @@ -15,7 +15,7 @@ "a": 1, "b": 0, }, - size=2 + size=2, ), 0.5, ), diff --git a/lumispy/utils/__init__.py b/lumispy/utils/__init__.py index 45b5b60eb..209bee982 100644 --- a/lumispy/utils/__init__.py +++ b/lumispy/utils/__init__.py @@ -17,16 +17,11 @@ # along with LumiSpy. If not, see . from .axes import ( - nm2eV, - eV2nm, axis2eV, data2eV, var2eV, - nm2invcm, - invcm2nm, axis2invcm, data2invcm, var2invcm, - join_spectra, solve_grating_equation, ) diff --git a/prepare_release.py b/prepare_release.py new file mode 100644 index 000000000..4fbef1f3a --- /dev/null +++ b/prepare_release.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +import argparse +import re +import subprocess + + +def run_towncrier(tag): + cmd = ("towncrier", "build", "--version", tag.strip("v")) + + return subprocess.call(cmd) + + +def update_fallback_version_in_pyproject(tag, fname="pyproject.toml"): + version = tag.strip("v").split(".") + # Default to +1 on minor version + major, minor = version[0], int(version[1]) + 1 + + with open(fname, "r") as file: + lines = file.readlines() + + pattern = "fallback_version" + new_version = f"{major}.{minor}.dev0" + # Iterate through the lines and find the pattern + for i, line in enumerate(lines): + if re.search(pattern, line): + lines[i] = f'{pattern} = "{new_version}"\n' + break + + # Write the updated content back to the file + with open(fname, "w") as file: + file.writelines(lines) + + print( + f"\nNew (fallback) dev version ({new_version}) written to `pyproject.toml`.\n" + ) + + +if __name__ == "__main__": + # Get tag argument + parser = argparse.ArgumentParser() + parser.add_argument("tag") + args = parser.parse_args() + tag = args.tag + + # Update release notes + run_towncrier(tag) + + # Update fallback version for setuptools_scm + update_fallback_version_in_pyproject(tag) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..c63f10e26 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,150 @@ +[build-system] +requires = ["setuptools>=64", "setuptools_scm>=8", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "lumispy" +authors = [{name = "The LumiSpy developers"}] +description = "Analysis of luminescence spectroscopy data with HyperSpy." +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3.8", + "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 :: Physics", + "Topic :: Software Development :: Libraries", +] +dependencies = [ + "hyperspy >= 1.7", # earlier versions do not provide non-uniform axes + "numpy", + "scipy", +] +keywords = [ + "CL", + "PL", + "EL", + "TRCL", + "TRPL", + "SEM", + "STEM", + "TEM", + "cathodoluminescence", + "photoluminescence", + "electroluminescence", + "Raman", + "curve fitting", + "data analysis", + "electron microscopy", + "hyperspectral", + "hyperspectrum", + "hyperspy", + "luminescence spectroscopy", + "lumispy", + "machine learning", + "model", + "multidimensional", + "numpy", + "python", + "scipy", + "spectroscopy", + "spectrum image", + "time-resolved", +] +dynamic = ["version"] +readme = "README.md" +requires-python = ">=3.8" + +[project.entry-points."hyperspy.extensions"] +lumispy = "lumispy" + +[project.license] +file = "LICENSE" + +[project.optional-dependencies] +tests = [ + "codecov", + "pytest>=5.0", + "pytest-cov", + "setuptools-scm", +] +doc = [ + "sphinx>=4.3.0", + "sphinx_rtd_theme>=0.5.1", + "sphinx-copybutton", + "sphinxcontrib-towncrier", + "towncrier", +] +dev = [ + "black", + "lumispy[doc]", + "lumispy[tests]" +] + +[project.urls] +"Bug Reports" = "https://github.com/lumispy/lumispy/issues" +"Conda-forge" = "https://anaconda.org/conda-forge/lumispy" +"Documentation" = "https://docs.lumispy.org" +"Homepage" = "https://lumispy.org" +"Source" = "https://github.com/lumispy/lumispy" + +[tool.coverage.report] +precision = 2 + +[tool.coverage.run] +branch = true +omit = [ + "lumispy/tests/*", + "prepare_release.py", +] +source = ["lumispy"] + +[tool.pytest.ini_options] +addopts = "-ra" +minversion = "5.0" +testpaths = ["lumispy/tests"] +norecursedirs = [ + "doc/_build/*" +] +xfail_strict = false +doctest_optionflags = [ + "IGNORE_EXCEPTION_DETAIL", + "NORMALIZE_WHITESPACE", + "ELLIPSIS", +] + +[tool.setuptools.package-data] +"*" = [ + "*.yaml", +] + +[tool.setuptools.packages.find] +include = ["lumispy*"] + +[tool.setuptools_scm] +# Presence enables setuptools_scm, the version will be determined at build time from git +# The version will be updated by the `prepare_release.py` script +fallback_version = "0.3.dev0" + +[tool.towncrier] +directory = "upcoming_changes/" +filename = "CHANGELOG.rst" +issue_format = "`#{issue} `_" +title_format = "{version} ({project_date})" +package_dir = "lumispy" +type = [ + { directory = "new", name = "New features", showcontent = true }, + { directory = "enhancements", name = "Enhancements", showcontent = true }, + { directory = "bugfix", name = "Bug Fixes", showcontent = true }, + { directory = "api", name = "API changes", showcontent = true }, + { directory = "deprecation", name = "Deprecations", showcontent = true }, + { directory = "doc", name = "Improved Documentation", showcontent = true }, + { directory = "maintenance", name = "Maintenance", showcontent = true }, +] diff --git a/releasing_guide.md b/releasing_guide.md index 7f8ed5f8d..c68357bff 100644 --- a/releasing_guide.md +++ b/releasing_guide.md @@ -5,17 +5,19 @@ To publish a new LumiSpy release do the following steps: ## Preparation - Create a new PR to the 'main' branch for the release process, e.g. `release_v0.1.1` -- Make sure to have the code ready, including changelog -- Set the correct version number in `lumispy/release_info.py` (increase the third - digit for a patch release, the second digit for a regular minor release, the - first digit for a major release) +- In a pull request, prepare the release by running the `prepare_release.py` python script + (e.g. `python prepare_release.py 0.1.1`), which will do the following: + - update the release notes in `CHANGES.rst` by running `towncrier`, + - update the `setuptools_scm` fallback version in `pyproject.toml` (for a patch release, this will stay the same). +- Check release notes - Let that PR collect comments for a day to ensure that other maintainers are comfortable with releasing - Set correct date and version number in `CHANGELOG.rst` ## Tag and Release -- Create a tag e.g. `git tag -a v0.1.1 -m "LumiSpy version 0.1.1"` +- Create a tag e.g. `git tag -a v0.1.1 -m "LumiSpy version 0.1.1"`. The lumispy version will + be set at build time from the tag by `setuptools_scm`. - Push tag to user fork for a test run `git push origin v0.1.1`. Will run the release workflow without uploading to PyPi - Push tag to LumiSpy repository to trigger release `git push upstream v0.1.1` @@ -24,8 +26,6 @@ To publish a new LumiSpy release do the following steps: ## Post-release action -- Increment the version and set it back to dev: `vx.y.zdev0` -- Update version in other branches if necessary - Prepare `CHANGELOG.rst` for development by adding `UNRELEASED` headline - Merge the PR diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index c16396fac..000000000 --- a/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[metadata] -license_files = LICENSE - diff --git a/setup.py b/setup.py deleted file mode 100644 index d92ec65d7..000000000 --- a/setup.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2019-2023 The LumiSpy developers -# -# This file is part of LumiSpy. -# -# LumiSpy 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. -# -# LumiSpy 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 LumiSpy. If not, see . - -from setuptools import setup, find_packages - -release_info = {} # grab release info -with open("lumispy/release_info.py") as f: - exec(f.read(), release_info) - -with open("README.md") as f: # grab readme - long_description = f.read() - -setup( - name="lumispy", - version=release_info["version"], - description=release_info["description"], - author=release_info["author"], - license=release_info["license"], - platforms=release_info["platforms"], - url=release_info["url"], - long_description=long_description, - long_description_content_type="text/markdown", - classifiers=[ - "Development Status :: 4 - Beta", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", - "Natural Language :: English", - "Operating System :: OS Independent", - "Programming Language :: Python :: 3.8", - "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 :: Physics", - "Topic :: Software Development :: Libraries", - ], - keywords=release_info["keywords"], - packages=find_packages(), - # adjust the tabbing - install_requires=[ - "hyperspy >= 1.7", # earlier versions do not provide non-uniform axes - "numpy", - "scipy", - ], - extras_require={ - "tests": ["pytest>=5.0"], - "coverage": ["pytest-cov", "codecov"], - "build-doc": [ - "sphinx>=4.3.0", - "sphinx_rtd_theme>=0.5.1", - "sphinx-copybutton", - ], - }, - package_data={ - "lumispy": ["*.py", "hyperspy_extension.yaml"], - }, - entry_points={"hyperspy.extensions": ["lumispy = lumispy"]}, - project_urls={ # Optional - "Bug Reports": "https://github.com/lumispy/lumispy/issues", - "Source": "https://github.com/lumispy/lumispy", - }, -) diff --git a/upcoming_changes/211.doc.rst b/upcoming_changes/211.doc.rst new file mode 100644 index 000000000..821d3575b --- /dev/null +++ b/upcoming_changes/211.doc.rst @@ -0,0 +1 @@ +Use ``towncrier`` to manage changelog diff --git a/upcoming_changes/211.maintenance.rst b/upcoming_changes/211.maintenance.rst new file mode 100644 index 000000000..1a9a88e21 --- /dev/null +++ b/upcoming_changes/211.maintenance.rst @@ -0,0 +1,5 @@ +Streamline project files and release workflow to match HyperSpy ecosystem: + +- Migrate to ``pyproject.toml`` from ``setup.py`` +- Use ``setuptools-scm`` to set version at build time +- Adapt release workflow, e.g. mine doi only after successful upload diff --git a/upcoming_changes/README.rst b/upcoming_changes/README.rst new file mode 100644 index 000000000..2bed8bbe1 --- /dev/null +++ b/upcoming_changes/README.rst @@ -0,0 +1,36 @@ +This directory contains "news fragments" which are short files that contain a small **ReST**-formatted +text that will be added to the next ``CHANGELOG``. + +The ``CHANGELOG`` will be read by **users**, so this description should be aimed to LumiSpy users +instead of describing internal changes which are only relevant to the developers. + +Each file should be named like ``..rst``, where +```` is an issue number, and ```` is one of: + +* ``new``: new user facing features, like new command-line options and new behavior. +* ``enhancements``: improvement of existing functionality, usually without requiring user intervention. +* ``bugfix``: fixes a bug. +* ``api``: a change which may break an existing script, such as feature removal or behavior change. +* ``deprecation``: feature deprecation. +* ``doc``: documentation improvement, like rewording an entire session or adding missing docs. +* ``maintenance``: a change related to the test suite, packaging, etc. + +So for example ``141.new.rst`` or ``273.bugfix.rst``. + +If your PR fixes an issue, use the number of the issue here. If there is no issue, +then after you submit the PR and get the PR number you can add a +changelog using that instead. + +If you are not sure what issue type to use, don't hesitate to ask in your PR. + +``towncrier`` preserves multiple paragraphs and formatting (code blocks, lists, and so on), but for entries +other than ``new`` it is usually better to stick to a single paragraph to keep it concise. For ``new``, +it is recommended to add a hyperlink to the user guide. + +To make a draft of the changelog, run from the command line: + + .. code-block:: bash + + $ towncrier build --draft + +See https://github.com/twisted/towncrier for more details.