Skip to content

Commit

Permalink
Merge pull request #25 from Colin-b/develop
Browse files Browse the repository at this point in the history
Release 1.0.0
  • Loading branch information
Colin-b committed May 21, 2021
2 parents 09a0502 + d1aa49d commit a04e29d
Show file tree
Hide file tree
Showing 19 changed files with 808 additions and 54 deletions.
18 changes: 17 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.0.0] - 2021-05-21
### Changed
- `keepachangelog.to_dict` now contains `url` key for each item if a link is available for the version.
- `keepachangelog.to_raw_dict` now contains `url` key for each item if a link is available for the version.
- `keepachangelog.to_dict` now contains `semantic_version` key for each item if the version follows semantic versioning.
- `keepachangelog.to_raw_dict` now contains `semantic_version` key for each item if the version follows semantic versioning.

### Added
- `keepachangelog.release` is now allowing to provide a custom new version thanks to the new `new_version` parameter.

### Fixed
- `keepachangelog.release` now allows `pre-release` and `build metadata` information as part of valid semantic version. As per [semantic versioning specifications](https://semver.org).
To ensure compatibility with some python specific versioning, `pre-release` is also handled as not being prefixed with `-`, or prefixed with `.`.
- `keepachangelog.release` will now bump a pre-release version to a stable version. It was previously failing.

## [0.5.0] - 2021-04-19
### Added
- `keepachangelog.release` function to guess new version number based on `Unreleased` section, update changelog and return new version number.
Expand Down Expand Up @@ -42,7 +57,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Initial release.

[Unreleased]: https://github.com/Colin-b/keepachangelog/compare/v0.5.0...HEAD
[Unreleased]: https://github.com/Colin-b/keepachangelog/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/Colin-b/keepachangelog/compare/v0.5.0...v1.0.0
[0.5.0]: https://github.com/Colin-b/keepachangelog/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/Colin-b/keepachangelog/compare/v0.3.1...v0.4.0
[0.3.1]: https://github.com/Colin-b/keepachangelog/compare/v0.3.0...v0.3.1
Expand Down
94 changes: 92 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<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>
<a href="https://travis-ci.com/Colin-b/keepachangelog"><img alt="Coverage" src="https://img.shields.io/badge/coverage-100%25-brightgreen"></a>
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
<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>
<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>
<a href="https://pypi.org/project/keepachangelog/"><img alt="Number of downloads" src="https://img.shields.io/pypi/dm/keepachangelog"></a>
</p>

Expand Down Expand Up @@ -38,6 +38,14 @@ changes = {
],
"release_date": "2018-05-31",
"version": "1.1.0",
"semantic_version": {
"major": 1,
"minor": 1,
"patch": 0,
"prerelease": None,
"buildmetadata": None,
},
"url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0",
},
"1.0.1": {
"fixed": [
Expand All @@ -48,11 +56,27 @@ changes = {
],
"release_date": "2018-05-31",
"version": "1.0.1",
"semantic_version": {
"major": 1,
"minor": 0,
"patch": 1,
"prerelease": None,
"buildmetadata": None,
},
"url": "https://github.test_url/test_project/compare/v1.0.0...v1.0.1",
},
"1.0.0": {
"deprecated": ["Known issue 1 (1.0.0)", "Known issue 2 (1.0.0)"],
"release_date": "2017-04-10",
"version": "1.0.0",
"semantic_version": {
"major": 1,
"minor": 0,
"patch": 0,
"prerelease": None,
"buildmetadata": None,
},
"url": "https://github.test_url/test_project/releases/tag/v1.0.0",
},
}
```
Expand Down Expand Up @@ -123,6 +147,72 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`show_unreleased` parameter can be specified in order to include `Unreleased` section information.
Note that `release_date` will be set to None in such as case.

### Retrieving the raw content

If for some reason you would like to retrieve the raw content of a release you can use `to_raw_dict` instead.

```python
import keepachangelog

changes = keepachangelog.to_raw_dict("path/to/CHANGELOG.md")
```

`changes` would look like:

```python
changes = {
"1.1.0": {
"raw": """### Changed
- Enhancement 1 (1.1.0)
- sub enhancement 1
- sub enhancement 2
- Enhancement 2 (1.1.0)""",
"release_date": "2018-05-31",
"version": "1.1.0",
"semantic_version": {
"major": 1,
"minor": 1,
"patch": 0,
"prerelease": None,
"buildmetadata": None,
},
"url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0",
},
"1.0.1": {
"raw": """### Fixed
- Bug fix 1 (1.0.1)
- sub bug 1
- sub bug 2
- Bug fix 2 (1.0.1)""",
"release_date": "2018-05-31",
"version": "1.0.1",
"semantic_version": {
"major": 1,
"minor": 0,
"patch": 1,
"prerelease": None,
"buildmetadata": None,
},
"url": "https://github.test_url/test_project/compare/v1.0.0...v1.0.1",
},
"1.0.0": {
"raw": """### Deprecated
- Known issue 1 (1.0.0)
- Known issue 2 (1.0.0)""",
"release_date": "2017-04-10",
"version": "1.0.0",
"semantic_version": {
"major": 1,
"minor": 0,
"patch": 0,
"prerelease": None,
"buildmetadata": None,
},
"url": "https://github.test_url/test_project/releases/tag/v1.0.0",
},
}
```

## Release

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

This will:
* Guess the new version number and return it:
* If `new_version` parameter is not provided, guess the new version number and return it:
* `Removed` or `Changed` sections will be considered as breaking changes, thus incrementing the major version.
* If the only section is `Fixed`, only patch will be incremented.
* Otherwise, minor will be incremented.
Expand Down
49 changes: 38 additions & 11 deletions keepachangelog/_changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
import re
from typing import Dict, List, Optional

from keepachangelog._versioning import guess_unreleased_version
from keepachangelog._versioning import (
actual_version,
guess_unreleased_version,
to_semantic,
InvalidSemanticVersion,
)


def is_release(line: str) -> bool:
Expand All @@ -21,10 +26,14 @@ def add_release(changes: Dict[str, dict], line: str, show_unreleased: bool) -> d
if not show_unreleased and not release_date:
return {}
version = unlink(version)
return changes.setdefault(
version,
{"version": version, "release_date": extract_date(release_date)},
)

release_details = {"version": version, "release_date": extract_date(release_date)}
try:
release_details["semantic_version"] = to_semantic(version)
except InvalidSemanticVersion:
pass

return changes.setdefault(version, release_details)


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


def is_information(line: str) -> bool:
return line and not link_pattern.fullmatch(line)
def is_link(line: str) -> bool:
return link_pattern.fullmatch(line) is not None


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

def to_dict(changelog_path: str, *, show_unreleased: bool = False) -> Dict[str, dict]:
changes = {}
# As URLs can be defined before actual usage, maintain a separate dict
urls = {}
with open(changelog_path) as change_log:
current_release = {}
category = []
Expand All @@ -71,14 +82,22 @@ def to_dict(changelog_path: str, *, show_unreleased: bool = False) -> Dict[str,
current_release = add_release(changes, line, show_unreleased)
elif is_category(line):
category = add_category(current_release, line)
elif is_information(line):
elif is_link(line):
link_match = link_pattern.fullmatch(line)
urls[link_match.group(1).lower()] = link_match.group(2)
elif line:
add_information(category, line)

for version, url in urls.items():
changes.get(version, {})["url"] = url

return changes


def to_raw_dict(changelog_path: str) -> Dict[str, dict]:
changes = {}
# As URLs can be defined before actual usage, maintain a separate dict
urls = {}
with open(changelog_path) as change_log:
current_release = {}
for line in change_log:
Expand All @@ -88,15 +107,23 @@ def to_raw_dict(changelog_path: str) -> Dict[str, dict]:
current_release = add_release(
changes, clean_line, show_unreleased=False
)
elif is_category(clean_line) or is_information(clean_line):
elif is_link(clean_line):
link_match = link_pattern.fullmatch(clean_line)
urls[link_match.group(1).lower()] = link_match.group(2)
elif clean_line:
current_release["raw"] = current_release.get("raw", "") + line

for version, url in urls.items():
changes.get(version, {})["url"] = url

return changes


def release(changelog_path: str) -> str:
def release(changelog_path: str, new_version: str = None) -> str:
changelog = to_dict(changelog_path, show_unreleased=True)
current_version, new_version = guess_unreleased_version(changelog)
current_version, current_semantic_version = actual_version(changelog)
if not new_version:
new_version = guess_unreleased_version(changelog, current_semantic_version)
release_version(changelog_path, current_version, new_version)
return new_version

Expand Down
Loading

0 comments on commit a04e29d

Please sign in to comment.