Skip to content

Commit

Permalink
fix: make compatible with towncrier>=24.7
Browse files Browse the repository at this point in the history
towncrier 24.7 changed the way that its find_fragments() function works
to accept a Config dataclass instead of specific components of the
config. This commit adds a new version of lookup_towncrier_fragments()
to use the new API and chooses which one to use based on the version
of towncrier obtained from importlib.metadata. It also slightly
changes the way that towncrier config can be obtained: the previous
get_towncrier_config() function (which returned a dict) is now renamed
as get_towncrier_config_as_dict() and get_towncrier_config() returns
the new Config dataclass object for towncrier versions above 22.12.0rc1
and raises NotImplementedError for older versions. This API change
should be ok as get_towncrier_config() was only called in one place
before.
  • Loading branch information
Ben Rowland authored and webknjaz committed Dec 21, 2024
1 parent dcc063f commit c209b0b
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 2 deletions.
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ classifiers =
[options]
include_package_data = True
install_requires =
packaging
sphinx
towncrier >= 19.2
package_dir =
Expand Down
52 changes: 50 additions & 2 deletions src/sphinxcontrib/towncrier/_fragment_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@


from functools import lru_cache
from importlib.metadata import version
from pathlib import Path
from typing import Optional, Set

from sphinx.util import logging

from packaging.version import Version


try:
# pylint: disable=no-name-in-module
Expand All @@ -17,7 +20,9 @@
find_fragments,
)

from ._towncrier import get_towncrier_config # noqa: WPS436
from ._towncrier import ( # noqa: WPS436
get_towncrier_config, get_towncrier_config_as_dict,
)


logger = logging.getLogger(__name__)
Expand All @@ -42,11 +47,21 @@ def _find_config_file(base: Path) -> Path:
# pylint: disable=fixme
# FIXME: refactor `lookup_towncrier_fragments` to drop noqas
@lru_cache(maxsize=1, typed=True) # noqa: WPS210
def lookup_towncrier_fragments( # noqa: WPS210
def lookup_towncrier_fragments(
working_dir: Optional[str] = None,
config_path: Optional[str] = None,
) -> Set[Path]:
"""Emit RST-formatted Towncrier changelog fragment paths."""
tc_version = Version(version('towncrier'))
if tc_version >= Version('24.7.0'):
return _lookup_towncrier_fragments_post24_7(working_dir, config_path)
return _lookup_towncrier_fragments_pre24_7(working_dir, config_path)


# used for towncrier version 24.7 and above
def _lookup_towncrier_fragments_post24_7( # noqa: WPS210
working_dir: Optional[str] = None, config_path: Optional[str] = None,
) -> Set[Path]:
project_path = Path.cwd() if working_dir is None else Path(working_dir)

final_config_path = (
Expand All @@ -66,6 +81,39 @@ def lookup_towncrier_fragments( # noqa: WPS210
)
return set()

fragment_dir = (towncrier_config.directory or 'newsfragments')
fragment_base_directory = project_path / fragment_dir

_fragments, fragment_filenames = find_fragments(
str(fragment_base_directory), towncrier_config, strict=False,
)

return {Path(fname[0]) for fname in fragment_filenames}


# used for versions of towncrier before 24.7
def _lookup_towncrier_fragments_pre24_7( # noqa: WPS210
working_dir: Optional[str] = None, config_path: Optional[str] = None,
) -> Set[Path]:
project_path = Path.cwd() if working_dir is None else Path(working_dir)

final_config_path = (
_resolve_spec_config(project_path, config_path)
or _find_config_file(project_path)
)

try:
towncrier_config = get_towncrier_config_as_dict(
project_path,
final_config_path,
)
except KeyError as key_err:
# NOTE: The error is missing key 'towncrier' or similar
logger.warning(
f'Missing key {key_err!s} in file {final_config_path!s}',
)
return set()

fragment_directory: Optional[str] = 'newsfragments'
try:
fragment_base_directory = project_path / towncrier_config['directory']
Expand Down
17 changes: 17 additions & 0 deletions src/sphinxcontrib/towncrier/_towncrier.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"""Towncrier related shims."""

from dataclasses import asdict as _dataclass_to_dict
from importlib.metadata import version
from pathlib import Path
from typing import Any, Dict, Union

from packaging.version import Version


try:
# Towncrier >= 22.8.0rc1
Expand All @@ -19,6 +22,20 @@


def get_towncrier_config(
project_path: Path,
final_config_path: Union[Path, None],
) -> Any:
"""Return the towncrier config in native format."""
tc_version = Version(version('towncrier'))
if tc_version >= Version('22.12.0rc1'):
return load_config_from_file(str(project_path), str(final_config_path))
raise NotImplementedError(
'Towncrier Config is not available before version 22.12.0rc1, consider '
'using "get_towncrier_config_as_dict()" instead',
)


def get_towncrier_config_as_dict(
project_path: Path,
final_config_path: Union[Path, None],
) -> Dict[str, Any]: # FIXME: add a better type # pylint: disable=fixme
Expand Down

0 comments on commit c209b0b

Please sign in to comment.