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.