-
-
Notifications
You must be signed in to change notification settings - Fork 339
Expand file tree
/
Copy pathbase.py
More file actions
113 lines (93 loc) · 4.29 KB
/
base.py
File metadata and controls
113 lines (93 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
from __future__ import annotations
from abc import ABCMeta
from pathlib import Path
from typing import IO, TYPE_CHECKING, Any, ClassVar
from commitizen.changelog import IncrementalMergeInfo, Metadata
from commitizen.config.base_config import BaseConfig
from commitizen.git import GitTag
from commitizen.tags import TagRules, VersionTag
from commitizen.version_schemes import get_version_scheme
from . import ChangelogFormat
if TYPE_CHECKING:
from commitizen.config.base_config import BaseConfig
class BaseFormat(ChangelogFormat, metaclass=ABCMeta):
"""
Base class to extend to implement a changelog file format.
"""
extension: ClassVar[str] = ""
alternative_extensions: ClassVar[set[str]] = set()
def __init__(self, config: BaseConfig) -> None:
# Constructor needs to be redefined because `Protocol` prevent instantiation by default
# See: https://bugs.python.org/issue44807
self.config = config
self.tag_rules = TagRules(
scheme=get_version_scheme(self.config.settings),
tag_format=self.config.settings["tag_format"],
legacy_tag_formats=self.config.settings["legacy_tag_formats"],
ignored_tag_formats=self.config.settings["ignored_tag_formats"],
)
def get_metadata(self, filepath: str) -> Metadata:
file = Path(filepath)
if not file.is_file():
return Metadata()
with file.open(encoding=self.config.settings["encoding"]) as changelog_file:
return self.get_metadata_from_file(changelog_file)
def get_metadata_from_file(self, file: IO[Any]) -> Metadata:
meta = Metadata()
unreleased_level: int | None = None
for index, line in enumerate(file):
line = line.strip().lower()
unreleased: int | None = None
if "unreleased" in line:
unreleased = self.parse_title_level(line)
# Try to find beginning and end lines of the unreleased block
if unreleased:
meta.unreleased_start = index
unreleased_level = unreleased
continue
elif unreleased_level and self.parse_title_level(line) == unreleased_level:
meta.unreleased_end = index
# Try to find the latest release done
parsed_version = self.parse_version_from_title(line)
if parsed_version:
meta.latest_version = parsed_version.version
meta.latest_version_tag = parsed_version.tag
meta.latest_version_position = index
break # there's no need for more info
if meta.unreleased_start is not None and meta.unreleased_end is None:
meta.unreleased_end = index
return meta
def get_latest_full_release(self, filepath: str) -> IncrementalMergeInfo:
file = Path(filepath)
if not file.is_file():
return IncrementalMergeInfo()
with file.open(encoding=self.config.settings["encoding"]) as changelog_file:
return self.get_latest_full_release_from_file(changelog_file)
def get_latest_full_release_from_file(self, file: IO[Any]) -> IncrementalMergeInfo:
latest_version_index: int | None = None
for index, line in enumerate(file):
latest_version_index = index
line = line.strip().lower()
parsed_version = self.parse_version_from_title(line)
if (
parsed_version
and not self.tag_rules.extract_version(
GitTag(parsed_version.tag, "", "")
).is_prerelease
):
return IncrementalMergeInfo(name=parsed_version.tag, index=index)
return IncrementalMergeInfo(index=latest_version_index)
def parse_version_from_title(self, line: str) -> VersionTag | None:
"""
Extract the version from a title line if any
"""
raise NotImplementedError(
"Default `get_metadata_from_file` requires `parse_version_from_changelog` to be implemented"
)
def parse_title_level(self, line: str) -> int | None:
"""
Get the title level/type of a line if any
"""
raise NotImplementedError(
"Default `get_metadata_from_file` requires `parse_title_type_of_line` to be implemented"
)