diff --git a/RELEASE.rst b/RELEASE.rst index a8842341..a3e91576 100644 --- a/RELEASE.rst +++ b/RELEASE.rst @@ -19,9 +19,9 @@ The same branch is used for the release candidate and the final release. In the end, the release branch is merged into the main branch. Update the version to the release candidate with the first being ``rc1`` (as opposed to 0). -In ``src/towncrier/_version.py`` the version is set using a PEP440 compliant string: +In ``pyproject.toml`` the version is set using a PEP440 compliant string: - __version__ = "19.9.0rc1" + version = "19.9.0rc1" Run ``venv/bin/towncrier build --yes`` to generate the news release NEWS file. Commit and push to the primary repository, not a fork. @@ -84,9 +84,9 @@ Final release Once the PR is approved, you can trigger the final release. Update the version to the final version. -In ``src/towncrier/_version.py`` the version is set using a PEP440 compliant string: +In ``pyproject.toml`` the version is set using a PEP440 compliant string: - __version__ = "19.9.0" + version = "19.9.0" Manually update the `NEWS.rst` file to include the final release version and date. Usually it will look like this. @@ -115,9 +115,9 @@ Similar to the release candidate, with the difference: No need for another review request. Update the version to the development version. -In ``src/towncrier/_version.py`` the version is set using a PEP440 compliant string: +In ``pyproject.toml`` the version is set using a PEP440 compliant string: - __version__ = "19.9.0.dev0" + version = "19.9.0.dev0" Commit and push the changes. diff --git a/docs/conf.py b/docs/conf.py index a59bfbf9..f98d50c8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -32,8 +32,10 @@ import os from datetime import date +from importlib.metadata import version -from towncrier import __version__ as towncrier_version + +towncrier_version = version("towncrier") extensions = [] diff --git a/pyproject.toml b/pyproject.toml index 4e46bdc5..97b4052e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,8 +4,12 @@ build-backend = "hatchling.build" [project] -dynamic = ["version"] name = "towncrier" +# For dev - 23.11.0.dev0 +# For RC - 23.11.0rc1 (release candidate starts at 1) +# For final - 23.11.0 +# make sure to follow PEP440 +version = "24.7.2.dev0" description = "Building newsfiles for your project." readme = "README.rst" license = "MIT" @@ -55,12 +59,6 @@ Tests = "https://github.com/twisted/towncrier/actions?query=branch%3Atrunk" Coverage = "https://codecov.io/gh/twisted/towncrier" Distribution = "https://pypi.org/project/towncrier" - -[tool.hatch.version] -source = "code" -path = "src/towncrier/_version.py" -expression = "_hatchling_version" - [tool.hatch.build] exclude = [ "admin", diff --git a/src/towncrier/__init__.py b/src/towncrier/__init__.py index a7578e17..0c504e1f 100644 --- a/src/towncrier/__init__.py +++ b/src/towncrier/__init__.py @@ -4,27 +4,3 @@ """ towncrier, a builder for your news files. """ - -from __future__ import annotations - - -__all__ = ["__version__"] - - -def __getattr__(name: str) -> str: - if name != "__version__": - raise AttributeError(f"module {__name__} has no attribute {name}") - - import warnings - - from ._version import __version__ - - warnings.warn( - "Accessing towncrier.__version__ is deprecated and will be " - "removed in a future release. Use importlib.metadata directly " - "to query for towncrier's packaging metadata.", - DeprecationWarning, - stacklevel=2, - ) - - return __version__ diff --git a/src/towncrier/_project.py b/src/towncrier/_project.py index 7b3a98c8..c09b1467 100644 --- a/src/towncrier/_project.py +++ b/src/towncrier/_project.py @@ -8,19 +8,14 @@ from __future__ import annotations import contextlib +import importlib.metadata import sys from importlib import import_module -from importlib.metadata import version as metadata_version +from importlib.metadata import PackageNotFoundError from types import ModuleType -if sys.version_info >= (3, 10): - from importlib.metadata import packages_distributions -else: - from importlib_metadata import packages_distributions # type: ignore - - def _get_package(package_dir: str, package: str) -> ModuleType: try: module = import_module(package) @@ -46,12 +41,11 @@ def _get_metadata_version(package: str) -> str | None: """ Try to get the version from the package metadata. """ - distributions = packages_distributions() - distribution_names = distributions.get(package) - if not distribution_names or len(distribution_names) != 1: - # We can only determine the version if there is exactly one matching distribution. - return None - return metadata_version(distribution_names[0]) + with contextlib.suppress(PackageNotFoundError): + if version := importlib.metadata.version(package): + return version + + return None def get_version(package_dir: str, package: str) -> str: diff --git a/src/towncrier/_shell.py b/src/towncrier/_shell.py index 6e9ae171..ba069aed 100644 --- a/src/towncrier/_shell.py +++ b/src/towncrier/_shell.py @@ -11,7 +11,6 @@ import click -from ._version import __version__ from .build import _main as _build_cmd from .check import _main as _check_cmd from .click_default_group import DefaultGroup @@ -19,7 +18,7 @@ @click.group(cls=DefaultGroup, default="build", default_if_no_args=True) -@click.version_option(__version__) +@click.version_option() def cli() -> None: """ Towncrier is a utility to produce useful, summarised news files for your project. diff --git a/src/towncrier/_version.py b/src/towncrier/_version.py deleted file mode 100644 index 7eebff72..00000000 --- a/src/towncrier/_version.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -Provides towncrier version information. -""" - -# For dev - 23.11.0.dev0 -# For RC - 23.11.0rc1 (release candidate starts at 1) -# For final - 23.11.0 -# make sure to follow PEP440 -__version__ = "24.7.2.dev0" - -_hatchling_version = __version__ -__all__ = ["_hatchling_version"] diff --git a/src/towncrier/newsfragments/640.misc b/src/towncrier/newsfragments/640.misc new file mode 100644 index 00000000..32f045c1 --- /dev/null +++ b/src/towncrier/newsfragments/640.misc @@ -0,0 +1 @@ +Use importlib.metadata to get the towncrier's version. diff --git a/src/towncrier/newsfragments/640.removal b/src/towncrier/newsfragments/640.removal new file mode 100644 index 00000000..a5fb5b82 --- /dev/null +++ b/src/towncrier/newsfragments/640.removal @@ -0,0 +1,3 @@ +Moved towncrier version definition from src/towncrier/_version.py to pyproject.toml + +towncrier.__version__ was removed, after being deprecated in 23.6.0. diff --git a/src/towncrier/test/test_packaging.py b/src/towncrier/test/test_packaging.py deleted file mode 100644 index 199adffd..00000000 --- a/src/towncrier/test/test_packaging.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) Amber Brown, 2015 -# See LICENSE for details. - -from twisted.trial.unittest import TestCase - -import towncrier - - -class TestPackaging(TestCase): - def test_version_attr(self): - """ - towncrier.__version__ was deprecated, but still exists for now. - """ - - def access__version(): - return towncrier.__version__ - - expected_warning = ( - "Accessing towncrier.__version__ is deprecated and will be " - "removed in a future release. Use importlib.metadata directly " - "to query for towncrier's packaging metadata." - ) - - self.assertWarns( - DeprecationWarning, expected_warning, __file__, access__version - )