Skip to content

Commit a04e29d

Browse files
authored
Merge pull request #25 from Colin-b/develop
Release 1.0.0
2 parents 09a0502 + d1aa49d commit a04e29d

19 files changed

+808
-54
lines changed

CHANGELOG.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
## [1.0.0] - 2021-05-21
10+
### Changed
11+
- `keepachangelog.to_dict` now contains `url` key for each item if a link is available for the version.
12+
- `keepachangelog.to_raw_dict` now contains `url` key for each item if a link is available for the version.
13+
- `keepachangelog.to_dict` now contains `semantic_version` key for each item if the version follows semantic versioning.
14+
- `keepachangelog.to_raw_dict` now contains `semantic_version` key for each item if the version follows semantic versioning.
15+
16+
### Added
17+
- `keepachangelog.release` is now allowing to provide a custom new version thanks to the new `new_version` parameter.
18+
19+
### Fixed
20+
- `keepachangelog.release` now allows `pre-release` and `build metadata` information as part of valid semantic version. As per [semantic versioning specifications](https://semver.org).
21+
To ensure compatibility with some python specific versioning, `pre-release` is also handled as not being prefixed with `-`, or prefixed with `.`.
22+
- `keepachangelog.release` will now bump a pre-release version to a stable version. It was previously failing.
23+
924
## [0.5.0] - 2021-04-19
1025
### Added
1126
- `keepachangelog.release` function to guess new version number based on `Unreleased` section, update changelog and return new version number.
@@ -42,7 +57,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4257
### Added
4358
- Initial release.
4459

45-
[Unreleased]: https://github.com/Colin-b/keepachangelog/compare/v0.5.0...HEAD
60+
[Unreleased]: https://github.com/Colin-b/keepachangelog/compare/v1.0.0...HEAD
61+
[1.0.0]: https://github.com/Colin-b/keepachangelog/compare/v0.5.0...v1.0.0
4662
[0.5.0]: https://github.com/Colin-b/keepachangelog/compare/v0.4.0...v0.5.0
4763
[0.4.0]: https://github.com/Colin-b/keepachangelog/compare/v0.3.1...v0.4.0
4864
[0.3.1]: https://github.com/Colin-b/keepachangelog/compare/v0.3.0...v0.3.1

README.md

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<a href="https://travis-ci.com/Colin-b/keepachangelog"><img alt="Build status" src="https://api.travis-ci.com/Colin-b/keepachangelog.svg?branch=master"></a>
66
<a href="https://travis-ci.com/Colin-b/keepachangelog"><img alt="Coverage" src="https://img.shields.io/badge/coverage-100%25-brightgreen"></a>
77
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
8-
<a href="https://travis-ci.com/Colin-b/keepachangelog"><img alt="Number of tests" src="https://img.shields.io/badge/tests-28 passed-blue"></a>
8+
<a href="https://travis-ci.com/Colin-b/keepachangelog"><img alt="Number of tests" src="https://img.shields.io/badge/tests-31 passed-blue"></a>
99
<a href="https://pypi.org/project/keepachangelog/"><img alt="Number of downloads" src="https://img.shields.io/pypi/dm/keepachangelog"></a>
1010
</p>
1111

@@ -38,6 +38,14 @@ changes = {
3838
],
3939
"release_date": "2018-05-31",
4040
"version": "1.1.0",
41+
"semantic_version": {
42+
"major": 1,
43+
"minor": 1,
44+
"patch": 0,
45+
"prerelease": None,
46+
"buildmetadata": None,
47+
},
48+
"url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0",
4149
},
4250
"1.0.1": {
4351
"fixed": [
@@ -48,11 +56,27 @@ changes = {
4856
],
4957
"release_date": "2018-05-31",
5058
"version": "1.0.1",
59+
"semantic_version": {
60+
"major": 1,
61+
"minor": 0,
62+
"patch": 1,
63+
"prerelease": None,
64+
"buildmetadata": None,
65+
},
66+
"url": "https://github.test_url/test_project/compare/v1.0.0...v1.0.1",
5167
},
5268
"1.0.0": {
5369
"deprecated": ["Known issue 1 (1.0.0)", "Known issue 2 (1.0.0)"],
5470
"release_date": "2017-04-10",
5571
"version": "1.0.0",
72+
"semantic_version": {
73+
"major": 1,
74+
"minor": 0,
75+
"patch": 0,
76+
"prerelease": None,
77+
"buildmetadata": None,
78+
},
79+
"url": "https://github.test_url/test_project/releases/tag/v1.0.0",
5680
},
5781
}
5882
```
@@ -123,6 +147,72 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
123147
`show_unreleased` parameter can be specified in order to include `Unreleased` section information.
124148
Note that `release_date` will be set to None in such as case.
125149

150+
### Retrieving the raw content
151+
152+
If for some reason you would like to retrieve the raw content of a release you can use `to_raw_dict` instead.
153+
154+
```python
155+
import keepachangelog
156+
157+
changes = keepachangelog.to_raw_dict("path/to/CHANGELOG.md")
158+
```
159+
160+
`changes` would look like:
161+
162+
```python
163+
changes = {
164+
"1.1.0": {
165+
"raw": """### Changed
166+
- Enhancement 1 (1.1.0)
167+
- sub enhancement 1
168+
- sub enhancement 2
169+
- Enhancement 2 (1.1.0)""",
170+
"release_date": "2018-05-31",
171+
"version": "1.1.0",
172+
"semantic_version": {
173+
"major": 1,
174+
"minor": 1,
175+
"patch": 0,
176+
"prerelease": None,
177+
"buildmetadata": None,
178+
},
179+
"url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0",
180+
},
181+
"1.0.1": {
182+
"raw": """### Fixed
183+
- Bug fix 1 (1.0.1)
184+
- sub bug 1
185+
- sub bug 2
186+
- Bug fix 2 (1.0.1)""",
187+
"release_date": "2018-05-31",
188+
"version": "1.0.1",
189+
"semantic_version": {
190+
"major": 1,
191+
"minor": 0,
192+
"patch": 1,
193+
"prerelease": None,
194+
"buildmetadata": None,
195+
},
196+
"url": "https://github.test_url/test_project/compare/v1.0.0...v1.0.1",
197+
},
198+
"1.0.0": {
199+
"raw": """### Deprecated
200+
- Known issue 1 (1.0.0)
201+
- Known issue 2 (1.0.0)""",
202+
"release_date": "2017-04-10",
203+
"version": "1.0.0",
204+
"semantic_version": {
205+
"major": 1,
206+
"minor": 0,
207+
"patch": 0,
208+
"prerelease": None,
209+
"buildmetadata": None,
210+
},
211+
"url": "https://github.test_url/test_project/releases/tag/v1.0.0",
212+
},
213+
}
214+
```
215+
126216
## Release
127217

128218
You can create a new release by using `keepachangelog.release` function.
@@ -134,7 +224,7 @@ new_version = keepachangelog.release("path/to/CHANGELOG.md")
134224
```
135225

136226
This will:
137-
* Guess the new version number and return it:
227+
* If `new_version` parameter is not provided, guess the new version number and return it:
138228
* `Removed` or `Changed` sections will be considered as breaking changes, thus incrementing the major version.
139229
* If the only section is `Fixed`, only patch will be incremented.
140230
* Otherwise, minor will be incremented.

keepachangelog/_changelog.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
import re
33
from typing import Dict, List, Optional
44

5-
from keepachangelog._versioning import guess_unreleased_version
5+
from keepachangelog._versioning import (
6+
actual_version,
7+
guess_unreleased_version,
8+
to_semantic,
9+
InvalidSemanticVersion,
10+
)
611

712

813
def is_release(line: str) -> bool:
@@ -21,10 +26,14 @@ def add_release(changes: Dict[str, dict], line: str, show_unreleased: bool) -> d
2126
if not show_unreleased and not release_date:
2227
return {}
2328
version = unlink(version)
24-
return changes.setdefault(
25-
version,
26-
{"version": version, "release_date": extract_date(release_date)},
27-
)
29+
30+
release_details = {"version": version, "release_date": extract_date(release_date)}
31+
try:
32+
release_details["semantic_version"] = to_semantic(version)
33+
except InvalidSemanticVersion:
34+
pass
35+
36+
return changes.setdefault(version, release_details)
2837

2938

3039
def unlink(value: str) -> str:
@@ -51,8 +60,8 @@ def add_category(release: dict, line: str) -> List[str]:
5160
link_pattern = re.compile(r"^\[(.*)\]: (.*)$")
5261

5362

54-
def is_information(line: str) -> bool:
55-
return line and not link_pattern.fullmatch(line)
63+
def is_link(line: str) -> bool:
64+
return link_pattern.fullmatch(line) is not None
5665

5766

5867
def add_information(category: List[str], line: str):
@@ -61,6 +70,8 @@ def add_information(category: List[str], line: str):
6170

6271
def to_dict(changelog_path: str, *, show_unreleased: bool = False) -> Dict[str, dict]:
6372
changes = {}
73+
# As URLs can be defined before actual usage, maintain a separate dict
74+
urls = {}
6475
with open(changelog_path) as change_log:
6576
current_release = {}
6677
category = []
@@ -71,14 +82,22 @@ def to_dict(changelog_path: str, *, show_unreleased: bool = False) -> Dict[str,
7182
current_release = add_release(changes, line, show_unreleased)
7283
elif is_category(line):
7384
category = add_category(current_release, line)
74-
elif is_information(line):
85+
elif is_link(line):
86+
link_match = link_pattern.fullmatch(line)
87+
urls[link_match.group(1).lower()] = link_match.group(2)
88+
elif line:
7589
add_information(category, line)
7690

91+
for version, url in urls.items():
92+
changes.get(version, {})["url"] = url
93+
7794
return changes
7895

7996

8097
def to_raw_dict(changelog_path: str) -> Dict[str, dict]:
8198
changes = {}
99+
# As URLs can be defined before actual usage, maintain a separate dict
100+
urls = {}
82101
with open(changelog_path) as change_log:
83102
current_release = {}
84103
for line in change_log:
@@ -88,15 +107,23 @@ def to_raw_dict(changelog_path: str) -> Dict[str, dict]:
88107
current_release = add_release(
89108
changes, clean_line, show_unreleased=False
90109
)
91-
elif is_category(clean_line) or is_information(clean_line):
110+
elif is_link(clean_line):
111+
link_match = link_pattern.fullmatch(clean_line)
112+
urls[link_match.group(1).lower()] = link_match.group(2)
113+
elif clean_line:
92114
current_release["raw"] = current_release.get("raw", "") + line
93115

116+
for version, url in urls.items():
117+
changes.get(version, {})["url"] = url
118+
94119
return changes
95120

96121

97-
def release(changelog_path: str) -> str:
122+
def release(changelog_path: str, new_version: str = None) -> str:
98123
changelog = to_dict(changelog_path, show_unreleased=True)
99-
current_version, new_version = guess_unreleased_version(changelog)
124+
current_version, current_semantic_version = actual_version(changelog)
125+
if not new_version:
126+
new_version = guess_unreleased_version(changelog, current_semantic_version)
100127
release_version(changelog_path, current_version, new_version)
101128
return new_version
102129

0 commit comments

Comments
 (0)