Skip to content

Commit c5fbf68

Browse files
committed
Refactored the template contexts.
- Changed `GroupedCommit` to `GroupingContext` - Added `ChangelogContext` as a root context for templates.
1 parent b7d0f61 commit c5fbf68

4 files changed

Lines changed: 58 additions & 21 deletions

File tree

generate_changelog/context.py

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
"""Context definitions."""
2-
from typing import List, Optional, Tuple
1+
"""Context definitions used in templates."""
2+
from typing import Callable, List, Optional, Tuple
33

44
import collections
55
import datetime
66
import re
77
from dataclasses import dataclass, field
88

9-
from generate_changelog.configuration import get_config
9+
from generate_changelog.configuration import Configuration, get_config
10+
from generate_changelog.utilities import diff_index
1011

1112

1213
@dataclass
@@ -87,7 +88,7 @@ def author_names(self) -> list:
8788

8889

8990
@dataclass
90-
class GroupedCommit:
91+
class GroupingContext:
9192
"""A combination of a tuple of the sorted values and a list of the CommitContexts in that group."""
9293

9394
grouping: Tuple[str]
@@ -113,8 +114,49 @@ class VersionContext:
113114
tagger: Optional[str] = None
114115
"""The name and email of the person who tagged this version in `name <email@ex.com>` format."""
115116

116-
grouped_commits: List[GroupedCommit] = field(default_factory=list)
117+
grouped_commits: List[GroupingContext] = field(default_factory=list)
117118
"""The sections that group the commits in this version."""
118119

119120
metadata: dict = field(default_factory=dict)
120121
"""Metadata for this version parsed from commits."""
122+
123+
124+
@dataclass
125+
class ChangelogContext:
126+
"""The primary context used when rendering a changelog."""
127+
128+
config: Configuration
129+
"""The changelog generation configuration."""
130+
131+
versions: List[VersionContext] = field(default_factory=list)
132+
"""The version contexts to render in the changelog."""
133+
134+
# Fields generated from the configuration post init
135+
136+
unreleased_label: str = field(init=False)
137+
"""The configured label used as the version title of the changes since the last valid tag."""
138+
139+
valid_author_tokens: List[str] = field(init=False, default_factory=list)
140+
"""The configured tokens in git commit trailers that indicate authorship."""
141+
142+
group_by: list[str] = field(init=False, default_factory=list)
143+
"""The configured grouping aspects for commits within a version."""
144+
145+
group_depth: int = field(init=False)
146+
"""The number of levels version commits are grouped by."""
147+
148+
diff_index: Callable = field(init=False)
149+
150+
def __post_init__(self):
151+
self.unreleased_label = self.config.unreleased_label
152+
self.valid_author_tokens = self.config.valid_author_tokens
153+
self.group_by = self.config.group_by
154+
self.group_depth = len(self.config.group_by)
155+
self.diff_index = diff_index
156+
157+
for var, val in self.config.rendered_variables.items():
158+
setattr(self, var, val)
159+
160+
def as_dict(self):
161+
"""Safely generate a dict version of this object."""
162+
return self.__dict__

generate_changelog/templates/commit.md.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
- {{ commit.summary }}
22
{{ commit.body|indent(2, first=True) }}
33
{% for key, val in commit.metadata["trailers"].items() %}
4-
{% if key not in VALID_AUTHOR_TOKENS %}
4+
{% if key not in valid_author_tokens %}
55
**{{ key }}:** {{ val|join(", ") }}
66

77
{% endif %}

generate_changelog/templating.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
from generate_changelog import git_ops
1111
from generate_changelog.actions.metadata import MetadataCollector
1212
from generate_changelog.configuration import Configuration, get_config
13-
from generate_changelog.context import CommitContext, GroupedCommit, VersionContext
13+
from generate_changelog.context import ChangelogContext, CommitContext, GroupingContext, VersionContext
1414
from generate_changelog.pipeline import Action, pipeline_factory
1515

16-
from .utilities import diff_index, resolve_name
16+
from .utilities import resolve_name
1717

1818

1919
def get_default_env(config: Optional[Configuration] = None):
@@ -163,7 +163,7 @@ def key_func(input_value) -> tuple:
163163
return tuple((i is not None, i) for i in input_value[0])
164164

165165
sorted_groups = sorted(commit_groups.items(), key=key_func)
166-
return [GroupedCommit(*item) for item in sorted_groups]
166+
return [GroupingContext(*item) for item in sorted_groups]
167167

168168

169169
def render(repository: Repo, config: Configuration, starting_tag: Optional[str] = None) -> str:
@@ -179,18 +179,13 @@ def render(repository: Repo, config: Configuration, starting_tag: Optional[str]
179179
The full or partial changelog
180180
"""
181181
version_context = get_context_from_tags(repository, config, starting_tag)
182-
context = config.variables.copy()
183-
context["versions"] = version_context
184-
context["VALID_AUTHOR_TOKENS"] = config.valid_author_tokens
185-
context["diff_index"] = diff_index
186-
context["group_depth"] = len(config.group_by)
187-
182+
context = ChangelogContext(config=config, versions=version_context)
188183
if starting_tag:
189184
heading_str = get_default_env(config).get_template("heading.md.jinja").render()
190-
versions_str = get_default_env(config).get_template("versions.md.jinja").render(context)
185+
versions_str = get_default_env(config).get_template("versions.md.jinja").render(context.as_dict())
191186
return "\n".join([heading_str, versions_str])
192187

193-
return get_default_env(config).get_template("base.md.jinja").render(context)
188+
return get_default_env(config).get_template("base.md.jinja").render(context.as_dict())
194189

195190

196191
def first_matching(actions: list, commit: CommitContext) -> str:

test/test_templating.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
import datetime
33
import textwrap
44
from pathlib import Path
5-
from test import conftest
65

76
import pytest
8-
from conftest import commit_factory
97
from faker import Faker
108
from pytest import param
119

1210
from generate_changelog import configuration, templating
1311
from generate_changelog.configuration import DEFAULT_COMMIT_CLASSIFIERS, get_default_config
1412
from generate_changelog.context import CommitContext
1513

14+
from .conftest import commit_factory
15+
1616
FIXTURES_DIR = Path(__file__).parent / "fixtures"
1717
fake = Faker()
1818

@@ -40,7 +40,7 @@ def test_first_matching(string, expected):
4040

4141
def test_commit_context():
4242
"""CommitContexts should properly parse things."""
43-
commit = conftest.commit_factory()
43+
commit = commit_factory()
4444
context = CommitContext(
4545
sha=commit.hexsha,
4646
commit_datetime=commit.committed_datetime,
@@ -57,7 +57,7 @@ def test_commit_context():
5757

5858
def test_commit_with_no_email():
5959
"""A trailer without an email should still get parsed."""
60-
commit = conftest.commit_factory()
60+
commit = commit_factory()
6161
name_only = fake.name()
6262
context = CommitContext(
6363
sha=commit.hexsha,

0 commit comments

Comments
 (0)