diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 9dadaa450..4afe44428 100644 --- 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 CHANGES.rst, +- [ ] add a changelog entry in the `upcoming_changes` folder (see [`upcoming_changes/README.rst`](https://github.com/hyperspy/exspy/blob/main/upcoming_changes/README.rst)), +- [ ] Check formatting of the changelog entry (and eventual user guide changes) in the `docs/readthedocs.org:exspy` 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/tests.yml b/.github/workflows/tests.yml index 5387835a0..75f525b21 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,6 +25,20 @@ jobs: steps: - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: get repository name + shell: bash + run: echo "REPOSITORY_NAME=${GITHUB_REPOSITORY#*/}" >> $GITHUB_ENV + + - name: Fetch tags upstream + if: ${{ github.repository_owner != 'hyperspy' }} + # Needs to fetch the tags from upstream to get the + # correct version with setuptools_scm + run: | + git remote add upstream https://github.com/hyperspy/${{ env.REPOSITORY_NAME }}.git + git fetch upstream --tags - uses: actions/setup-python@v4 name: Install Python @@ -37,7 +51,6 @@ jobs: pip --version - name: Install - shell: bash run: | pip install -e .[tests] diff --git a/.gitignore b/.gitignore index ccb49562c..9b2aef230 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ doc/_build/* doc/auto_examples/* +doc/sg_execution_times.rst build/* dist/* *egg-info* diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 015d38882..f11b9ac62 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -10,6 +10,9 @@ build: os: ubuntu-22.04 tools: python: "3.11" + jobs: + post_checkout: + - git fetch --unshallow || true # Build documentation in the docs/ directory with Sphinx sphinx: @@ -20,8 +23,8 @@ formats: - htmlzip python: - install: - - method: pip - path: . - extra_requirements: - - doc + install: + - method: pip + path: . + extra_requirements: + - doc diff --git a/CHANGES.rst b/CHANGES.rst index 97ecc327c..3012caab3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,10 +2,12 @@ Changelog ********* Changelog entries for the development version are available at -https://holospy.readthedocs.io/en/latest/changes.html +https://exspy.readthedocs.io/en/latest/changes.html -0.1.dev0 (UNRELEASED) -===================== + +.. towncrier-draft-entries:: |release| [UNRELEASED] + +.. towncrier release notes start - Enable ``signal_range`` arguments when using ``subpixel=True`` in :py:meth:`~.signals.EELSSpectrum.align_zero_loss_peak` (`#7 `_) - Support for tabulated :ref:`Generalised Oscillator Strengths (GOS) ` using the diff --git a/doc/conf.py b/doc/conf.py index 7c4ea7c78..7f459f6fa 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -14,9 +14,16 @@ # import sys # sys.path.insert(0, os.path.abspath('.')) +import hyperspy.api as hs +import logging import numpydoc from packaging.version import Version + +# Set logging level to `ERROR` to avoid exspy warning in documentation +hs.set_log_level("ERROR") + + # -- Project information ----------------------------------------------------- project = "exSpy" @@ -42,6 +49,7 @@ "sphinx.ext.intersphinx", "sphinx.ext.napoleon", "sphinx_gallery.gen_gallery", + "sphinxcontrib.towncrier", ] linkcheck_ignore = [ @@ -147,3 +155,10 @@ copybutton_prompt_text = r">>> |\.\.\. " copybutton_prompt_is_regexp = True + +# -- 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/exspy/__init__.py b/exspy/__init__.py index 61271b919..f3cf1bb7c 100644 --- a/exspy/__init__.py +++ b/exspy/__init__.py @@ -1,3 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2007-2023 The exSpy developers +# +# This file is part of exSpy. +# +# exSpy 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. +# +# exSpy 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 exSpy. If not, see . + +from importlib.metadata import version from pathlib import Path from . import components @@ -8,16 +27,29 @@ from ._defaults_parser import preferences -if Path(__file__).parent.parent.name == "site-packages": # pragma: no cover - # Tested in the "build" workflow on GitHub CI - from importlib.metadata import version +__version__ = version("exspy") + +# 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 + +# 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 - __version__ = version("rosettasciio") -else: - # Editable install - from setuptools_scm import get_version +# 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(Path(__file__).parent.parent) + __version__ = get_version(_root) + except ImportError: # pragma: no cover + # setuptools_scm not installed, we keep the existing __version__ + pass __all__ = [ 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 index f92a4d8b2..ba616acc8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,6 +68,8 @@ file = "LICENSE" "sphinx-design", "sphinx-favicon", "sphinx-gallery", + "sphinxcontrib-towncrier", + "towncrier", ] "tests" = [ "pytest >= 5.0", @@ -96,7 +98,10 @@ force-exclude = ''' [tool.coverage.run] branch = true source = ["hyperspy"] -omit = ["hyperspy/tests/*"] +omit = [ + "hyperspy/tests/*", + "prepare_release.py", + ] [tool.coverage.report] precision = 2 @@ -118,3 +123,48 @@ include = ["exspy*"] [tool.setuptools_scm] # Presence enables setuptools_scm, the version will be determine at build time from git +# The version will be updated by the `prepare_release.py` script +fallback_version = "0.1.dev0" + + +[tool.towncrier] +package_dir = "exspy" +filename = "CHANGES.rst" +directory = "upcoming_changes/" +title_format = "{version} ({project_date})" +issue_format = "`#{issue} `_" + + [[tool.towncrier.type]] + directory = "new" + name = "New features" + showcontent = true + + [[tool.towncrier.type]] + directory = "bugfix" + name = "Bug Fixes" + showcontent = true + + [[tool.towncrier.type]] + directory = "doc" + name = "Improved Documentation" + showcontent = true + + [[tool.towncrier.type]] + directory = "deprecation" + name = "Deprecations" + showcontent = true + + [[tool.towncrier.type]] + directory = "enhancements" + name = "Enhancements" + showcontent = true + + [[tool.towncrier.type]] + directory = "api" + name = "API changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "maintenance" + name = "Maintenance" + showcontent = true diff --git a/releasing_guide.md b/releasing_guide.md index b211bc212..2de718f81 100644 --- a/releasing_guide.md +++ b/releasing_guide.md @@ -4,8 +4,10 @@ To publish a new exSpy 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 +- In a pull request, prepare the release by running the `prepare_release.py` python script (e.g. `python prepare_release.py 0.2`) , 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 `CHANGES.rst` diff --git a/upcoming_changes/14.maintenance.rst b/upcoming_changes/14.maintenance.rst new file mode 100644 index 000000000..5b627d765 --- /dev/null +++ b/upcoming_changes/14.maintenance.rst @@ -0,0 +1 @@ +Use towncrier to manage release notes and improve setting dev version \ No newline at end of file