Source code for generate_changelog.actions.matching
"""Commit matching functions."""
import operator as op
import re
from typing import Any, Callable, ClassVar, Dict, Optional
from generate_changelog.actions import register_builtin
from generate_changelog.context import CommitContext
[docs]
@register_builtin
class SummaryRegexMatch:
r"""
Matches the commit summary using a regular expression.
If ``pattern`` is ``None`` all commits will match.
Example:
In ``.changelog-config.yaml`` ::
commit_classifiers:
- action: SummaryRegexMatch
category: New
kwargs:
pattern: (?i)^(?:new|add)[^\n]*$
Args:
pattern: The pattern to match against the commit summary
"""
[docs]
def __init__(self, pattern: Optional[str] = None):
self.pattern = re.compile(pattern) if pattern else None
[docs]
def __call__(self, commit: CommitContext) -> bool:
"""Does the commit summary match the pattern?"""
if self.pattern is None:
return True
return re.search(self.pattern, commit.summary) is not None
[docs]
@register_builtin
class MetadataMatch:
"""
Evaluates an attribute in the metadata against a value using an operator.
Examples:
To group breaking changes::
- action: MetadataMatch
category: Breaking Changes
kwargs:
attribute: has_breaking_change
operator: is
value: True
To match a specific value::
- action: MetadataMatch
category: Feature
kwargs:
attribute: commit_type
operator: ==
value: feat
To match multiple values::
- action: MetadataMatch
category: Updates
kwargs:
attribute: commit_type
operator: in
value: ["fix", "refactor", "update"]
Valid operators: ``==``, ``!=``, ``<``, ``>``, ``>=``, ``<=``, ``is``, ``is not``, ``in``, ``not in``
Args:
attribute: The name of the metadata key whose value will be evaluated
operator: One of the valid operators described above
value: The value to evaluate the against the metadata
Raises:
ValueError: If the operator value is not recognized
"""
operator_map: ClassVar[Dict[str, Callable]] = {
"==": op.eq,
"!=": op.ne,
"<": op.lt,
">": op.gt,
">=": op.ge,
"<=": op.le,
"is": op.is_,
"is not": op.is_not,
"in": op.contains,
"not in": lambda x, y: x not in y,
}
"""Mapping of operator strings to functions for evaluation."""
[docs]
def __init__(self, attribute: str, operator: str, value: Any):
self.attribute = attribute
if operator not in self.operator_map:
raise ValueError(
f"'{operator}' is not a valid operator. Must be one of {', '.join(self.operator_map.keys())}."
)
self.operator = self.operator_map[operator]
self.value = value
self.swap_operands = operator in {"in", "not in"}
[docs]
def __call__(self, commit: CommitContext) -> bool:
"""Does the commit metadata attribute meet the conditional?"""
if self.attribute not in commit.metadata:
return False
attr_value = commit.metadata[self.attribute]
if self.swap_operands:
return self.operator(self.value, attr_value)
return self.operator(attr_value, self.value)