From 0519583df2fec2861cc5e0d4cd509511338c1cd3 Mon Sep 17 00:00:00 2001 From: Colin-b Date: Wed, 26 May 2021 16:38:43 +0200 Subject: [PATCH 1/8] Add uncategorized details to releases --- CHANGELOG.md | 6 ++ keepachangelog/_changelog.py | 38 ++++++++--- tests/test_changelog.py | 15 ++++- tests/test_changelog_no_category.py | 97 +++++++++++++++++++++++++++++ tests/test_changelog_unreleased.py | 2 + 5 files changed, 146 insertions(+), 12 deletions(-) create mode 100644 tests/test_changelog_no_category.py diff --git a/CHANGELOG.md b/CHANGELOG.md index a33ab6b..23d60df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Fixed +- `keepachangelog.to_dict` now contains releases that have a URL but no section. +- `keepachangelog.to_raw_dict` now contains releases that have a URL but no section. + +### Changed +- `keepachangelog.to_dict` now contains `uncategorized` key for each item if uncategorized information are available for the version. ## [1.0.0] - 2021-05-21 ### Changed diff --git a/keepachangelog/_changelog.py b/keepachangelog/_changelog.py index ce729e3..09aae7b 100644 --- a/keepachangelog/_changelog.py +++ b/keepachangelog/_changelog.py @@ -14,7 +14,7 @@ def is_release(line: str) -> bool: return line.startswith("## ") -def add_release(changes: Dict[str, dict], line: str, show_unreleased: bool) -> dict: +def add_release(changes: Dict[str, dict], line: str) -> dict: release_line = line[3:].lower().strip(" ") # A release is separated by a space between version and release date # Release pattern should match lines like: "[0.0.1] - 2020-12-31" or [Unreleased] @@ -23,8 +23,6 @@ def add_release(changes: Dict[str, dict], line: str, show_unreleased: bool) -> d if " " in release_line else (release_line, None) ) - if not show_unreleased and not release_date: - return {} version = unlink(version) release_details = {"version": version, "release_date": extract_date(release_date)} @@ -79,7 +77,8 @@ def to_dict(changelog_path: str, *, show_unreleased: bool = False) -> Dict[str, line = line.strip(" \n") if is_release(line): - current_release = add_release(changes, line, show_unreleased) + current_release = add_release(changes, line) + category = current_release.setdefault("uncategorized", []) elif is_category(line): category = add_category(current_release, line) elif is_link(line): @@ -88,8 +87,22 @@ def to_dict(changelog_path: str, *, show_unreleased: bool = False) -> Dict[str, elif line: add_information(category, line) + # Add url for each version (create version if not existing) for version, url in urls.items(): - changes.get(version, {})["url"] = url + changes.setdefault(version, {"version": version})["url"] = url + + # Avoid empty uncategorized + unreleased_version = None + for version, current_release in changes.items(): + if not current_release.get("uncategorized"): + current_release.pop("uncategorized", None) + + # If there is an empty release date, it identify the unreleased section + if ("release_date" in current_release) and not current_release["release_date"]: + unreleased_version = version + + if not show_unreleased: + changes.pop(unreleased_version, None) return changes @@ -104,17 +117,24 @@ def to_raw_dict(changelog_path: str) -> Dict[str, dict]: clean_line = line.strip(" \n") if is_release(clean_line): - current_release = add_release( - changes, clean_line, show_unreleased=False - ) + current_release = add_release(changes, 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 + # Add url for each version (create version if not existing) for version, url in urls.items(): - changes.get(version, {})["url"] = url + changes.setdefault(version, {"version": version})["url"] = url + + unreleased_version = None + for version, current_release in changes.items(): + # If there is an empty release date, it identify the unreleased section + if ("release_date" in current_release) and not current_release["release_date"]: + unreleased_version = version + + changes.pop(unreleased_version, None) return changes diff --git a/tests/test_changelog.py b/tests/test_changelog.py index 59159fe..65eb340 100644 --- a/tests/test_changelog.py +++ b/tests/test_changelog.py @@ -68,7 +68,8 @@ def changelog(tmpdir): - Known issue 2 (1.0.0) [Unreleased]: https://github.test_url/test_project/compare/v1.1.0...HEAD -[1.1.0]: https://github.test_url/test_project/compare/v1.0.1...v1.1.0 +[1.1.0]: https://github.test_url/test_project/compare/v1.0.2...v1.1.0 +[1.0.2]: https://github.test_url/test_project/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.test_url/test_project/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.test_url/test_project/releases/tag/v1.0.0 """ @@ -116,7 +117,11 @@ def test_changelog_with_versions_and_all_categories(changelog): "patch": 0, "prerelease": None, }, - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0", + "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", + }, + "1.0.2": { + "version": "1.0.2", + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", }, "1.0.1": { "fixed": [ @@ -204,7 +209,11 @@ def test_raw_changelog_with_versions_and_all_categories(changelog): "patch": 0, "prerelease": None, }, - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0", + "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", + }, + "1.0.2": { + "version": "1.0.2", + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", }, "1.0.1": { "raw": """### Fixed diff --git a/tests/test_changelog_no_category.py b/tests/test_changelog_no_category.py new file mode 100644 index 0000000..321b7bc --- /dev/null +++ b/tests/test_changelog_no_category.py @@ -0,0 +1,97 @@ +import os +import os.path + +import pytest + +import keepachangelog + + +@pytest.fixture +def changelog(tmpdir): + changelog_file_path = os.path.join(tmpdir, "CHANGELOG.md") + with open(changelog_file_path, "wt") as file: + file.write( + """# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [1.2.0] - 2018-06-01 +- Release note 1. +- Release note 2. + +### Fixed +- Bug fix 1 +- sub bug 1 +- sub bug 2 +- Bug fix 2 + +## [1.1.0] - 2018-05-31 +- Enhancement 1 (1.1.0) +- sub enhancement 1 +- sub enhancement 2 +- Enhancement 2 (1.1.0) + +## [1.0.1] - 2018-05-31 +- Bug fix 1 (1.0.1) +- sub bug 1 +- sub bug 2 +- Bug fix 2 (1.0.1) +""" + ) + return changelog_file_path + + +def test_changelog_without_category(changelog): + assert keepachangelog.to_dict(changelog) == { + "1.2.0": { + "uncategorized": ["Release note 1.", "Release note 2."], + "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], + "release_date": "2018-06-01", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, + }, + "1.1.0": { + "uncategorized": [ + "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": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, + }, + "1.0.1": { + "uncategorized": [ + "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": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, + }, + } diff --git a/tests/test_changelog_unreleased.py b/tests/test_changelog_unreleased.py index 11fcdc1..cff6d4d 100644 --- a/tests/test_changelog_unreleased.py +++ b/tests/test_changelog_unreleased.py @@ -18,6 +18,7 @@ def changelog(tmpdir): and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +- Release note 0. ### Changed - Release note 1. * Release note 2. @@ -88,6 +89,7 @@ def test_changelog_with_versions_and_all_categories(changelog): ], "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], "security": ["Known issue 1", "Known issue 2"], + "uncategorized": ["Release note 0."], "deprecated": ["Deprecated feature 1", "Future removal 2"], "removed": ["Deprecated feature 2", "Future removal 1"], "url": "https://github.test_url/test_project/compare/v1.1.0...HEAD", From aff22cc367c381abdda3a1d63a9f41cddbc03a37 Mon Sep 17 00:00:00 2001 From: Colin-b Date: Wed, 26 May 2021 18:23:47 +0200 Subject: [PATCH 2/8] Allow to convert from dict --- CHANGELOG.md | 3 ++ README.md | 14 +++++- keepachangelog/__init__.py | 2 +- keepachangelog/_changelog.py | 49 +++++++++++++++++++++ tests/test_changelog_unreleased.py | 69 ++++++++++++++++++++++++++++++ 5 files changed, 135 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23d60df..38fe605 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - `keepachangelog.to_dict` now contains `uncategorized` key for each item if uncategorized information are available for the version. +### Added +- `keepachangelog.from_dict` to create a changelog content based on a dictionary. + ## [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. diff --git a/README.md b/README.md index 195bb22..4e2f542 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,12 @@ Build status Coverage Code style: black -Number of tests +Number of tests Number of downloads

* [Convert to dict](#convert-changelog-to-dict) +* [Convert from dict](#convert-dict-to-changelog) * [Release a new version](#release) * [Add changelog retrieval REST API endpoint](#endpoint) * [Starlette](#starlette) @@ -213,6 +214,17 @@ changes = { } ``` +## Convert dict to changelog + +Convert a python dict (resulting from [`keepachangelog.to_dict`](#convert-changelog-to-dict)) to a changelog markdown content following [keep a changelog](https://keepachangelog.com/en/1.1.0/) format. + +```python +import keepachangelog + +changes = keepachangelog.to_dict("path/to/CHANGELOG.md") +content = keepachangelog.from_dict(changes) +``` + ## Release You can create a new release by using `keepachangelog.release` function. diff --git a/keepachangelog/__init__.py b/keepachangelog/__init__.py index 31e7d59..d40e7a6 100644 --- a/keepachangelog/__init__.py +++ b/keepachangelog/__init__.py @@ -1,2 +1,2 @@ from keepachangelog.version import __version__ -from keepachangelog._changelog import to_dict, to_raw_dict, release +from keepachangelog._changelog import to_dict, to_raw_dict, release, from_dict diff --git a/keepachangelog/_changelog.py b/keepachangelog/_changelog.py index 09aae7b..e71a044 100644 --- a/keepachangelog/_changelog.py +++ b/keepachangelog/_changelog.py @@ -107,6 +107,55 @@ def to_dict(changelog_path: str, *, show_unreleased: bool = False) -> Dict[str, return changes +def from_dict(changes: Dict[str, dict]): + content = """# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n""" + + for current_release in changes.values(): + content += f"\n## [{current_release['version'].capitalize()}]" + + if current_release.get("release_date"): + content += f" - {current_release['release_date']}" + + uncategorized = current_release.get("uncategorized", []) + for category_content in uncategorized: + content += f"\n* {category_content}" + if uncategorized: + content += "\n" + + for category_name, category_content in current_release.items(): + if category_name in [ + "version", + "release_date", + "uncategorized", + "semantic_version", + "url", + ]: + continue + + content += f"\n### {category_name.capitalize()}" + + for categorized in category_content: + content += f"\n- {categorized}" + + content += "\n" + + content += "\n" + + for current_release in changes.values(): + if not current_release.get("url"): + continue + + content += ( + f"[{current_release['version'].capitalize()}]: {current_release['url']}\n" + ) + + return content + + def to_raw_dict(changelog_path: str) -> Dict[str, dict]: changes = {} # As URLs can be defined before actual usage, maintain a separate dict diff --git a/tests/test_changelog_unreleased.py b/tests/test_changelog_unreleased.py index cff6d4d..7c7b5f9 100644 --- a/tests/test_changelog_unreleased.py +++ b/tests/test_changelog_unreleased.py @@ -144,3 +144,72 @@ def test_changelog_with_versions_and_all_categories(changelog): "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, } + + +def test_changelog_from_dict(changelog): + releases = keepachangelog.to_dict(changelog, show_unreleased=True) + + assert ( + keepachangelog.from_dict(releases) + == """# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] +* Release note 0. + +### Changed +- Release note 1. +- Release note 2. + +### Added +- Enhancement 1 +- sub enhancement 1 +- sub enhancement 2 +- Enhancement 2 + +### Fixed +- Bug fix 1 +- sub bug 1 +- sub bug 2 +- Bug fix 2 + +### Security +- Known issue 1 +- Known issue 2 + +### Deprecated +- Deprecated feature 1 +- Future removal 2 + +### Removed +- Deprecated feature 2 +- Future removal 1 + +## [1.1.0] - 2018-05-31 +### Changed +- Enhancement 1 (1.1.0) +- sub *enhancement 1* +- sub enhancement 2 +- Enhancement 2 (1.1.0) + +## [1.0.1] - 2018-05-31 +### Fixed +- Bug fix 1 (1.0.1) +- sub bug 1 +- sub bug 2 +- Bug fix 2 (1.0.1) + +## [1.0.0] - 2017-04-10 +### Deprecated +- Known issue 1 (1.0.0) +- Known issue 2 (1.0.0) + +[Unreleased]: https://github.test_url/test_project/compare/v1.1.0...HEAD +[1.1.0]: https://github.test_url/test_project/compare/v1.0.1...v1.1.0 +[1.0.1]: https://github.test_url/test_project/compare/v1.0.0...v1.0.1 +[1.0.0]: https://github.test_url/test_project/releases/tag/v1.0.0 +""" + ) From 968b38def21155110c6f91c2f4b9d18e5bb44b42 Mon Sep 17 00:00:00 2001 From: Colin-b Date: Wed, 26 May 2021 18:39:45 +0200 Subject: [PATCH 3/8] Allow to provide changelog as a buffer --- CHANGELOG.md | 1 + keepachangelog/_changelog.py | 16 ++++++- tests/test_changelog.py | 82 ++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38fe605..8724bfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `keepachangelog.from_dict` to create a changelog content based on a dictionary. +- `keepachangelog.to_dict` now allows to provide a context manager allowing to iterate on lines instead of a file path. ## [1.0.0] - 2021-05-21 ### Changed diff --git a/keepachangelog/_changelog.py b/keepachangelog/_changelog.py index e71a044..ff92480 100644 --- a/keepachangelog/_changelog.py +++ b/keepachangelog/_changelog.py @@ -67,10 +67,24 @@ def add_information(category: List[str], line: str): def to_dict(changelog_path: str, *, show_unreleased: bool = False) -> Dict[str, dict]: + """ + Convert changelog markdown file following keep a changelog format into python dict. + + :param changelog_path: Path to the changelog file, or context manager providing iteration on lines. + :param show_unreleased: Add unreleased section (if any) to the resulting dictionary. + :return python dict containing version as key and related changes as value. + """ changes = {} # As URLs can be defined before actual usage, maintain a separate dict urls = {} - with open(changelog_path) as change_log: + + # Allow for changelog as a file path or as a context manager providing content + try: + change_log = open(changelog_path) + except TypeError: + change_log = changelog_path + + with change_log: current_release = {} category = [] for line in change_log: diff --git a/tests/test_changelog.py b/tests/test_changelog.py index 65eb340..d6a4676 100644 --- a/tests/test_changelog.py +++ b/tests/test_changelog.py @@ -1,3 +1,4 @@ +import io import os import os.path @@ -157,6 +158,87 @@ def test_changelog_with_versions_and_all_categories(changelog): } +def test_changelog_with_versions_and_all_categories_as_file_reader(changelog): + with io.StringIO(open(changelog).read()) as file_reader: + assert keepachangelog.to_dict(file_reader) == { + "1.2.0": { + "added": [ + "Enhancement 1", + "sub enhancement 1", + "sub enhancement 2", + "Enhancement 2", + ], + "changed": ["Release note 1.", "Release note 2."], + "deprecated": ["Deprecated feature 1", "Future removal 2"], + "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], + "release_date": "2018-06-01", + "removed": ["Deprecated feature 2", "Future removal 1"], + "security": ["Known issue 1", "Known issue 2"], + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, + }, + "1.1.0": { + "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": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", + }, + "1.0.2": { + "version": "1.0.2", + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", + }, + "1.0.1": { + "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": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": 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": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/releases/tag/v1.0.0", + }, + } + + def test_raw_changelog_with_versions_and_all_categories(changelog): assert keepachangelog.to_raw_dict(changelog) == { "1.2.0": { From 357a7fe0e72b8e1e76e6d8f2c6caa69d42c9c6ce Mon Sep 17 00:00:00 2001 From: Colin-b Date: Wed, 26 May 2021 19:00:49 +0200 Subject: [PATCH 4/8] Expect any line iterable instead of a context manager --- CHANGELOG.md | 2 +- keepachangelog/_changelog.py | 51 ++++---- tests/test_changelog.py | 233 ++++++++++++----------------------- 3 files changed, 110 insertions(+), 176 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8724bfa..2b5ac04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `keepachangelog.from_dict` to create a changelog content based on a dictionary. -- `keepachangelog.to_dict` now allows to provide a context manager allowing to iterate on lines instead of a file path. +- `keepachangelog.to_dict` now allows to provide any line iterable instead of only a file path. ## [1.0.0] - 2021-05-21 ### Changed diff --git a/keepachangelog/_changelog.py b/keepachangelog/_changelog.py index ff92480..e029841 100644 --- a/keepachangelog/_changelog.py +++ b/keepachangelog/_changelog.py @@ -1,6 +1,6 @@ import datetime import re -from typing import Dict, List, Optional +from typing import Dict, List, Optional, Iterable, Union from keepachangelog._versioning import ( actual_version, @@ -66,7 +66,9 @@ def add_information(category: List[str], line: str): category.append(line.lstrip(" *-").rstrip(" -")) -def to_dict(changelog_path: str, *, show_unreleased: bool = False) -> Dict[str, dict]: +def to_dict( + changelog_path: Union[str, Iterable[str]], *, show_unreleased: bool = False +) -> Dict[str, dict]: """ Convert changelog markdown file following keep a changelog format into python dict. @@ -74,32 +76,33 @@ def to_dict(changelog_path: str, *, show_unreleased: bool = False) -> Dict[str, :param show_unreleased: Add unreleased section (if any) to the resulting dictionary. :return python dict containing version as key and related changes as value. """ - changes = {} - # As URLs can be defined before actual usage, maintain a separate dict - urls = {} - # Allow for changelog as a file path or as a context manager providing content try: - change_log = open(changelog_path) + with open(changelog_path) as change_log: + return _to_dict(change_log, show_unreleased) except TypeError: - change_log = changelog_path + return _to_dict(changelog_path, show_unreleased) - with change_log: - current_release = {} - category = [] - for line in change_log: - line = line.strip(" \n") - - if is_release(line): - current_release = add_release(changes, line) - category = current_release.setdefault("uncategorized", []) - elif is_category(line): - category = add_category(current_release, 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) + +def _to_dict(change_log: Iterable[str], show_unreleased: bool) -> Dict[str, dict]: + changes = {} + # As URLs can be defined before actual usage, maintain a separate dict + urls = {} + current_release = {} + category = [] + for line in change_log: + line = line.strip(" \n") + + if is_release(line): + current_release = add_release(changes, line) + category = current_release.setdefault("uncategorized", []) + elif is_category(line): + category = add_category(current_release, 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) # Add url for each version (create version if not existing) for version, url in urls.items(): diff --git a/tests/test_changelog.py b/tests/test_changelog.py index d6a4676..fc9d28d 100644 --- a/tests/test_changelog.py +++ b/tests/test_changelog.py @@ -78,165 +78,96 @@ def changelog(tmpdir): return changelog_file_path -def test_changelog_with_versions_and_all_categories(changelog): - assert keepachangelog.to_dict(changelog) == { - "1.2.0": { - "added": [ - "Enhancement 1", - "sub enhancement 1", - "sub enhancement 2", - "Enhancement 2", - ], - "changed": ["Release note 1.", "Release note 2."], - "deprecated": ["Deprecated feature 1", "Future removal 2"], - "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "2018-06-01", - "removed": ["Deprecated feature 2", "Future removal 1"], - "security": ["Known issue 1", "Known issue 2"], - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, - }, +changelog_as_dict = { + "1.2.0": { + "added": [ + "Enhancement 1", + "sub enhancement 1", + "sub enhancement 2", + "Enhancement 2", + ], + "changed": ["Release note 1.", "Release note 2."], + "deprecated": ["Deprecated feature 1", "Future removal 2"], + "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], + "release_date": "2018-06-01", + "removed": ["Deprecated feature 2", "Future removal 1"], + "security": ["Known issue 1", "Known issue 2"], + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, }, - "1.1.0": { - "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": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, - }, - "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", + }, + "1.1.0": { + "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": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, }, - "1.0.2": { - "version": "1.0.2", - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", - }, - "1.0.1": { - "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, - }, - "url": "https://github.test_url/test_project/compare/v1.0.0...v1.0.1", + "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", + }, + "1.0.2": { + "version": "1.0.2", + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", + }, + "1.0.1": { + "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": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, }, - "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, - }, - "url": "https://github.test_url/test_project/releases/tag/v1.0.0", + "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": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, }, - } + "url": "https://github.test_url/test_project/releases/tag/v1.0.0", + }, +} + + +def test_changelog_with_versions_and_all_categories(changelog): + assert keepachangelog.to_dict(changelog) == changelog_as_dict def test_changelog_with_versions_and_all_categories_as_file_reader(changelog): with io.StringIO(open(changelog).read()) as file_reader: - assert keepachangelog.to_dict(file_reader) == { - "1.2.0": { - "added": [ - "Enhancement 1", - "sub enhancement 1", - "sub enhancement 2", - "Enhancement 2", - ], - "changed": ["Release note 1.", "Release note 2."], - "deprecated": ["Deprecated feature 1", "Future removal 2"], - "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "2018-06-01", - "removed": ["Deprecated feature 2", "Future removal 1"], - "security": ["Known issue 1", "Known issue 2"], - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, - }, - }, - "1.1.0": { - "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": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, - }, - "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", - }, - "1.0.2": { - "version": "1.0.2", - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", - }, - "1.0.1": { - "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": 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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, - }, - "url": "https://github.test_url/test_project/releases/tag/v1.0.0", - }, - } + assert keepachangelog.to_dict(file_reader) == changelog_as_dict + + # Assert that file reader is not closed + file_reader.seek(0) + assert keepachangelog.to_dict(file_reader) == changelog_as_dict def test_raw_changelog_with_versions_and_all_categories(changelog): From d3a834df6420aaff6827794b43157ec46c08cc35 Mon Sep 17 00:00:00 2001 From: Colin-b Date: Wed, 26 May 2021 19:01:20 +0200 Subject: [PATCH 5/8] Keep the number of test cases up to date --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e2f542..34ef0a6 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Build status Coverage Code style: black -Number of tests +Number of tests Number of downloads

From 3a6102b94fd5fee66cc3e98c6b365e9f4fa653c6 Mon Sep 17 00:00:00 2001 From: Colin-b Date: Thu, 27 May 2021 10:42:42 +0200 Subject: [PATCH 6/8] Ensure behavior of from_dict with unlink sections or non existing one --- tests/test_changelog_unreleased.py | 33 +++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/tests/test_changelog_unreleased.py b/tests/test_changelog_unreleased.py index 7c7b5f9..a6d6aa4 100644 --- a/tests/test_changelog_unreleased.py +++ b/tests/test_changelog_unreleased.py @@ -66,8 +66,13 @@ def changelog(tmpdir): - Known issue 1 (1.0.0) - Known issue 2 (1.0.0) +## [0.0.1] - 2017-01-01 +### Added +- First release + [Unreleased]: https://github.test_url/test_project/compare/v1.1.0...HEAD -[1.1.0]: https://github.test_url/test_project/compare/v1.0.1...v1.1.0 +[1.1.0]: https://github.test_url/test_project/compare/v1.0.2...v1.1.0 +[1.0.2]: https://github.test_url/test_project/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.test_url/test_project/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.test_url/test_project/releases/tag/v1.0.0 """ @@ -110,7 +115,11 @@ def test_changelog_with_versions_and_all_categories(changelog): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0", + "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", + }, + "1.0.2": { + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", + "version": "1.0.2", }, "1.0.1": { "version": "1.0.1", @@ -143,6 +152,18 @@ def test_changelog_with_versions_and_all_categories(changelog): "deprecated": ["Known issue 1 (1.0.0)", "Known issue 2 (1.0.0)"], "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, + "0.0.1": { + "added": ["First release"], + "release_date": "2017-01-01", + "semantic_version": { + "buildmetadata": None, + "major": 0, + "minor": 0, + "patch": 1, + "prerelease": None, + }, + "version": "0.0.1", + }, } @@ -207,9 +228,15 @@ def test_changelog_from_dict(changelog): - Known issue 1 (1.0.0) - Known issue 2 (1.0.0) +## [0.0.1] - 2017-01-01 +### Added +- First release + +## [1.0.2] [Unreleased]: https://github.test_url/test_project/compare/v1.1.0...HEAD -[1.1.0]: https://github.test_url/test_project/compare/v1.0.1...v1.1.0 +[1.1.0]: https://github.test_url/test_project/compare/v1.0.2...v1.1.0 [1.0.1]: https://github.test_url/test_project/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.test_url/test_project/releases/tag/v1.0.0 +[1.0.2]: https://github.test_url/test_project/compare/v1.0.1...v1.0.2 """ ) From 1488abb4f02810710026737304a511d300437063 Mon Sep 17 00:00:00 2001 From: Colin-b Date: Thu, 27 May 2021 16:01:41 +0200 Subject: [PATCH 7/8] Add metadata information --- CHANGELOG.md | 4 + README.md | 122 +++++++------- keepachangelog/_changelog.py | 42 ++--- keepachangelog/_versioning.py | 4 +- keepachangelog/flask_restx.py | 23 +-- setup.py | 5 +- tests/test_changelog.py | 168 +++++++++++--------- tests/test_changelog_empty_version.py | 18 ++- tests/test_changelog_no_added.py | 72 +++++---- tests/test_changelog_no_category.py | 54 ++++--- tests/test_changelog_no_changed.py | 72 +++++---- tests/test_changelog_no_deprecated.py | 72 +++++---- tests/test_changelog_no_fixed.py | 72 +++++---- tests/test_changelog_no_removed.py | 72 +++++---- tests/test_changelog_no_security.py | 72 +++++---- tests/test_changelog_unreleased.py | 98 +++++++----- tests/test_flask_restx.py | 60 +++---- tests/test_non_standard_changelog.py | 220 ++++++++++++++------------ tests/test_starlette.py | 60 +++---- 19 files changed, 727 insertions(+), 583 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b5ac04..83de539 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - `keepachangelog.to_dict` now contains `uncategorized` key for each item if uncategorized information are available for the version. +- `keepachangelog.to_dict` now contains `metadata` key where `version`, `release_date`, `semantic_version` and `url` have been moved. +- `keepachangelog.to_raw_dict` now contains `metadata` key where `version`, `release_date`, `semantic_version` and `url` have been moved. +- As `keepachangelog.starlette.add_changelog_endpoint` is returning data as returned by `keepachangelog.to_dict`, the endpoint output is now modified. +- As `keepachangelog.flask_restx.add_changelog_endpoint` is returning data as returned by `keepachangelog.to_dict`, the endpoint output is now modified. ### Added - `keepachangelog.from_dict` to create a changelog content based on a dictionary. diff --git a/README.md b/README.md index 34ef0a6..d95175e 100644 --- a/README.md +++ b/README.md @@ -37,16 +37,18 @@ changes = { "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, + "metadata": { + "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", }, - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0", }, "1.0.1": { "fixed": [ @@ -55,29 +57,33 @@ changes = { "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, + "metadata": { + "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", }, - "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, + "metadata": { + "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", }, - "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, } ``` @@ -146,7 +152,7 @@ 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. +Note that `release_date` metadata will be set to None in such as case. ### Retrieving the raw content @@ -168,16 +174,18 @@ changes = { - 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, + "metadata": { + "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", }, - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0", }, "1.0.1": { "raw": """### Fixed @@ -185,31 +193,35 @@ changes = { - 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, + "metadata": { + "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", }, - "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, + "metadata": { + "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", }, - "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, } ``` diff --git a/keepachangelog/_changelog.py b/keepachangelog/_changelog.py index e029841..51a92dd 100644 --- a/keepachangelog/_changelog.py +++ b/keepachangelog/_changelog.py @@ -25,13 +25,13 @@ def add_release(changes: Dict[str, dict], line: str) -> dict: ) version = unlink(version) - release_details = {"version": version, "release_date": extract_date(release_date)} + metadata = {"version": version, "release_date": extract_date(release_date)} try: - release_details["semantic_version"] = to_semantic(version) + metadata["semantic_version"] = to_semantic(version) except InvalidSemanticVersion: pass - return changes.setdefault(version, release_details) + return changes.setdefault(version, {"metadata": metadata}) def unlink(value: str) -> str: @@ -106,16 +106,19 @@ def _to_dict(change_log: Iterable[str], show_unreleased: bool) -> Dict[str, dict # Add url for each version (create version if not existing) for version, url in urls.items(): - changes.setdefault(version, {"version": version})["url"] = url + changes.setdefault(version, {"metadata": {"version": version}})["metadata"][ + "url" + ] = url # Avoid empty uncategorized unreleased_version = None for version, current_release in changes.items(): + metadata = current_release["metadata"] if not current_release.get("uncategorized"): current_release.pop("uncategorized", None) # If there is an empty release date, it identify the unreleased section - if ("release_date" in current_release) and not current_release["release_date"]: + if ("release_date" in metadata) and not metadata["release_date"]: unreleased_version = version if not show_unreleased: @@ -132,10 +135,11 @@ def from_dict(changes: Dict[str, dict]): and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n""" for current_release in changes.values(): - content += f"\n## [{current_release['version'].capitalize()}]" + metadata = current_release["metadata"] + content += f"\n## [{metadata['version'].capitalize()}]" - if current_release.get("release_date"): - content += f" - {current_release['release_date']}" + if metadata.get("release_date"): + content += f" - {metadata['release_date']}" uncategorized = current_release.get("uncategorized", []) for category_content in uncategorized: @@ -144,13 +148,7 @@ def from_dict(changes: Dict[str, dict]): content += "\n" for category_name, category_content in current_release.items(): - if category_name in [ - "version", - "release_date", - "uncategorized", - "semantic_version", - "url", - ]: + if category_name in ["metadata", "uncategorized"]: continue content += f"\n### {category_name.capitalize()}" @@ -163,12 +161,11 @@ def from_dict(changes: Dict[str, dict]): content += "\n" for current_release in changes.values(): - if not current_release.get("url"): + metadata = current_release["metadata"] + if not metadata.get("url"): continue - content += ( - f"[{current_release['version'].capitalize()}]: {current_release['url']}\n" - ) + content += f"[{metadata['version'].capitalize()}]: {metadata['url']}\n" return content @@ -192,12 +189,15 @@ def to_raw_dict(changelog_path: str) -> Dict[str, dict]: # Add url for each version (create version if not existing) for version, url in urls.items(): - changes.setdefault(version, {"version": version})["url"] = url + changes.setdefault(version, {"metadata": {"version": version}})["metadata"][ + "url" + ] = url unreleased_version = None for version, current_release in changes.items(): + metadata = current_release["metadata"] # If there is an empty release date, it identify the unreleased section - if ("release_date" in current_release) and not current_release["release_date"]: + if ("release_date" in metadata) and not metadata["release_date"]: unreleased_version = version changes.pop(unreleased_version, None) diff --git a/keepachangelog/_versioning.py b/keepachangelog/_versioning.py index 216e426..b01e90f 100644 --- a/keepachangelog/_versioning.py +++ b/keepachangelog/_versioning.py @@ -85,9 +85,7 @@ def guess_unreleased_version(changelog: dict, current_semantic_version: dict) -> unreleased = changelog.get("unreleased", {}) # Only keep user provided entries unreleased = unreleased.copy() - unreleased.pop("version", None) - unreleased.pop("release_date", None) - unreleased.pop("url", None) + unreleased.pop("metadata", None) if not unreleased: raise Exception( "Release content must be provided within changelog Unreleased section." diff --git a/keepachangelog/flask_restx.py b/keepachangelog/flask_restx.py index 3e2710c..a718d64 100644 --- a/keepachangelog/flask_restx.py +++ b/keepachangelog/flask_restx.py @@ -25,15 +25,20 @@ def add_changelog_endpoint( namespace.model( "ChangelogReleaseModel", { - "version": flask_restx.fields.String( - description="Release version following semantic versioning.", - required=True, - example="3.12.5", - ), - "release_date": flask_restx.fields.Date( - description="Release date.", - required=True, - example="2019-12-31", + "metadata": namespace.model( + "ChangelogReleaseMetaDataModel", + { + "version": flask_restx.fields.String( + description="Release version following semantic versioning.", + required=True, + example="3.12.5", + ), + "release_date": flask_restx.fields.Date( + description="Release date.", + required=True, + example="2019-12-31", + ), + }, ), "added": flask_restx.fields.List( flask_restx.fields.String(description="New features.") diff --git a/setup.py b/setup.py index 3d7ac26..17deebe 100644 --- a/setup.py +++ b/setup.py @@ -39,11 +39,10 @@ extras_require={ "testing": [ # Used to check starlette endpoint - "requests", + "requests==2.*", "starlette==0.13.*", # Used to check flask-restx endpoint - "flask==1.*", - "flask-restx==0.2.*", + "flask-restx==0.4.*", # Used to check coverage "pytest-cov==2.*", ] diff --git a/tests/test_changelog.py b/tests/test_changelog.py index fc9d28d..961be91 100644 --- a/tests/test_changelog.py +++ b/tests/test_changelog.py @@ -89,16 +89,18 @@ def changelog(tmpdir): "changed": ["Release note 1.", "Release note 2."], "deprecated": ["Deprecated feature 1", "Future removal 2"], "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "2018-06-01", "removed": ["Deprecated feature 2", "Future removal 1"], "security": ["Known issue 1", "Known issue 2"], - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-06-01", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { @@ -108,20 +110,24 @@ def changelog(tmpdir): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "release_date": "2018-05-31", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", }, - "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", }, "1.0.2": { - "version": "1.0.2", - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", + "metadata": { + "version": "1.0.2", + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", + } }, "1.0.1": { "fixed": [ @@ -130,29 +136,33 @@ def changelog(tmpdir): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "2018-05-31", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/compare/v1.0.0...v1.0.1", }, - "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-04-10", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, - "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, } @@ -196,14 +206,16 @@ def test_raw_changelog_with_versions_and_all_categories(changelog): - Deprecated feature 2 - Future removal 1 """, - "release_date": "2018-06-01", - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-06-01", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { @@ -213,20 +225,24 @@ def test_raw_changelog_with_versions_and_all_categories(changelog): - sub enhancement 2 - Enhancement 2 (1.1.0) """, - "release_date": "2018-05-31", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", }, - "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", }, "1.0.2": { - "version": "1.0.2", - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", + "metadata": { + "version": "1.0.2", + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", + }, }, "1.0.1": { "raw": """### Fixed @@ -235,31 +251,35 @@ def test_raw_changelog_with_versions_and_all_categories(changelog): - sub bug 2 - Bug fix 2 (1.0.1) """, - "release_date": "2018-05-31", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/compare/v1.0.0...v1.0.1", }, - "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-04-10", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, - "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, } diff --git a/tests/test_changelog_empty_version.py b/tests/test_changelog_empty_version.py index 43845c8..b2dc644 100644 --- a/tests/test_changelog_empty_version.py +++ b/tests/test_changelog_empty_version.py @@ -52,16 +52,18 @@ def test_changelog_with_empty_version(changelog): "changed": ["Release note 1.", "Release note 2."], "deprecated": ["Deprecated feature 1", "Future removal 2"], "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "2018-06-01", "removed": ["Deprecated feature 2", "Future removal 1"], "security": ["Known issue 1", "Known issue 2"], - "version": "", - "semantic_version": { - "buildmetadata": None, - "major": 0, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-06-01", + "version": "", + "semantic_version": { + "buildmetadata": None, + "major": 0, + "minor": 0, + "patch": 0, + "prerelease": None, + }, }, }, } diff --git a/tests/test_changelog_no_added.py b/tests/test_changelog_no_added.py index 32d6d03..271dfcb 100644 --- a/tests/test_changelog_no_added.py +++ b/tests/test_changelog_no_added.py @@ -71,16 +71,18 @@ def test_changelog_with_versions_and_no_added(changelog): "changed": ["Release note 1.", "Release note 2."], "deprecated": ["Deprecated feature 1", "Future removal 2"], "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "2018-06-01", "removed": ["Deprecated feature 2", "Future removal 1"], "security": ["Known issue 1", "Known issue 2"], - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-06-01", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { @@ -90,14 +92,16 @@ def test_changelog_with_versions_and_no_added(changelog): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "release_date": "2018-05-31", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, }, }, "1.0.1": { @@ -107,26 +111,30 @@ def test_changelog_with_versions_and_no_added(changelog): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "2018-05-31", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, }, }, "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-04-10", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, }, }, } diff --git a/tests/test_changelog_no_category.py b/tests/test_changelog_no_category.py index 321b7bc..3ac2667 100644 --- a/tests/test_changelog_no_category.py +++ b/tests/test_changelog_no_category.py @@ -50,14 +50,16 @@ def test_changelog_without_category(changelog): "1.2.0": { "uncategorized": ["Release note 1.", "Release note 2."], "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "2018-06-01", - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-06-01", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { @@ -67,14 +69,16 @@ def test_changelog_without_category(changelog): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "release_date": "2018-05-31", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, }, }, "1.0.1": { @@ -84,14 +88,16 @@ def test_changelog_without_category(changelog): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "2018-05-31", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, }, }, } diff --git a/tests/test_changelog_no_changed.py b/tests/test_changelog_no_changed.py index 242363f..4bf6550 100644 --- a/tests/test_changelog_no_changed.py +++ b/tests/test_changelog_no_changed.py @@ -73,27 +73,31 @@ def test_changelog_with_versions_and_no_changed(changelog): ], "deprecated": ["Deprecated feature 1", "Future removal 2"], "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "2018-06-01", "removed": ["Deprecated feature 2", "Future removal 1"], "security": ["Known issue 1", "Known issue 2"], - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-06-01", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { - "release_date": "2018-05-31", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, }, }, "1.0.1": { @@ -103,26 +107,30 @@ def test_changelog_with_versions_and_no_changed(changelog): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "2018-05-31", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, }, }, "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-04-10", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, }, }, } diff --git a/tests/test_changelog_no_deprecated.py b/tests/test_changelog_no_deprecated.py index cc70e0a..cfaa9e9 100644 --- a/tests/test_changelog_no_deprecated.py +++ b/tests/test_changelog_no_deprecated.py @@ -75,16 +75,18 @@ def test_changelog_with_versions_and_no_deprecated(changelog): ], "changed": ["Release note 1.", "Release note 2."], "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "2018-06-01", "removed": ["Deprecated feature 2", "Future removal 1"], "security": ["Known issue 1", "Known issue 2"], - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-06-01", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { @@ -94,14 +96,16 @@ def test_changelog_with_versions_and_no_deprecated(changelog): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "release_date": "2018-05-31", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, }, }, "1.0.1": { @@ -111,25 +115,29 @@ def test_changelog_with_versions_and_no_deprecated(changelog): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "2018-05-31", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, }, }, "1.0.0": { - "release_date": "2017-04-10", - "version": "1.0.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-04-10", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, }, }, } diff --git a/tests/test_changelog_no_fixed.py b/tests/test_changelog_no_fixed.py index ecde986..2f1fa93 100644 --- a/tests/test_changelog_no_fixed.py +++ b/tests/test_changelog_no_fixed.py @@ -76,16 +76,18 @@ def test_changelog_with_versions_and_no_fixed(changelog): ], "changed": ["Release note 1.", "Release note 2."], "deprecated": ["Deprecated feature 1", "Future removal 2"], - "release_date": "2018-06-01", "removed": ["Deprecated feature 2", "Future removal 1"], "security": ["Known issue 1", "Known issue 2"], - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-06-01", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { @@ -95,14 +97,16 @@ def test_changelog_with_versions_and_no_fixed(changelog): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "release_date": "2018-05-31", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, }, }, "1.0.1": { @@ -112,26 +116,30 @@ def test_changelog_with_versions_and_no_fixed(changelog): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "2018-05-31", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, }, }, "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-04-10", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, }, }, } diff --git a/tests/test_changelog_no_removed.py b/tests/test_changelog_no_removed.py index 18de621..be1fde1 100644 --- a/tests/test_changelog_no_removed.py +++ b/tests/test_changelog_no_removed.py @@ -79,15 +79,17 @@ def test_changelog_with_versions_and_no_removed(changelog): "changed": ["Release note 1.", "Release note 2."], "deprecated": ["Deprecated feature 1", "Future removal 2"], "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "2018-06-01", "security": ["Known issue 1", "Known issue 2"], - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-06-01", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { @@ -97,14 +99,16 @@ def test_changelog_with_versions_and_no_removed(changelog): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "release_date": "2018-05-31", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, }, }, "1.0.1": { @@ -114,26 +118,30 @@ def test_changelog_with_versions_and_no_removed(changelog): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "2018-05-31", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, }, }, "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-04-10", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, }, }, } diff --git a/tests/test_changelog_no_security.py b/tests/test_changelog_no_security.py index 1ddd0e8..1fc21d3 100644 --- a/tests/test_changelog_no_security.py +++ b/tests/test_changelog_no_security.py @@ -79,15 +79,17 @@ def test_changelog_with_versions_and_no_security(changelog): "changed": ["Release note 1.", "Release note 2."], "deprecated": ["Deprecated feature 1", "Future removal 2"], "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "2018-06-01", "removed": ["Deprecated feature 2", "Future removal 1"], - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-06-01", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { @@ -97,14 +99,16 @@ def test_changelog_with_versions_and_no_security(changelog): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "release_date": "2018-05-31", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, }, }, "1.0.1": { @@ -114,26 +118,30 @@ def test_changelog_with_versions_and_no_security(changelog): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "2018-05-31", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, }, }, "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-04-10", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, }, }, } diff --git a/tests/test_changelog_unreleased.py b/tests/test_changelog_unreleased.py index a6d6aa4..4f2044c 100644 --- a/tests/test_changelog_unreleased.py +++ b/tests/test_changelog_unreleased.py @@ -83,8 +83,6 @@ def changelog(tmpdir): def test_changelog_with_versions_and_all_categories(changelog): assert keepachangelog.to_dict(changelog, show_unreleased=True) == { "unreleased": { - "version": "unreleased", - "release_date": None, "changed": ["Release note 1.", "Release note 2."], "added": [ "Enhancement 1", @@ -97,72 +95,86 @@ def test_changelog_with_versions_and_all_categories(changelog): "uncategorized": ["Release note 0."], "deprecated": ["Deprecated feature 1", "Future removal 2"], "removed": ["Deprecated feature 2", "Future removal 1"], - "url": "https://github.test_url/test_project/compare/v1.1.0...HEAD", + "metadata": { + "version": "unreleased", + "release_date": None, + "url": "https://github.test_url/test_project/compare/v1.1.0...HEAD", + }, }, "1.1.0": { - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, - }, - "release_date": "2018-05-31", "changed": [ "Enhancement 1 (1.1.0)", "sub *enhancement 1*", "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", + "metadata": { + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, + "release_date": "2018-05-31", + "url": "https://github.test_url/test_project/compare/v1.0.2...v1.1.0", + }, }, "1.0.2": { - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", - "version": "1.0.2", + "metadata": { + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", + "version": "1.0.2", + }, }, "1.0.1": { - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, - }, - "release_date": "2018-05-31", "fixed": [ "Bug fix 1 (1.0.1)", "sub bug 1", "sub bug 2", "Bug fix 2 (1.0.1)", ], - "url": "https://github.test_url/test_project/compare/v1.0.0...v1.0.1", + "metadata": { + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, + "release_date": "2018-05-31", + "url": "https://github.test_url/test_project/compare/v1.0.0...v1.0.1", + }, }, "1.0.0": { - "version": "1.0.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, - }, - "release_date": "2017-04-10", "deprecated": ["Known issue 1 (1.0.0)", "Known issue 2 (1.0.0)"], - "url": "https://github.test_url/test_project/releases/tag/v1.0.0", + "metadata": { + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, + "release_date": "2017-04-10", + "url": "https://github.test_url/test_project/releases/tag/v1.0.0", + }, }, "0.0.1": { "added": ["First release"], - "release_date": "2017-01-01", - "semantic_version": { - "buildmetadata": None, - "major": 0, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2017-01-01", + "semantic_version": { + "buildmetadata": None, + "major": 0, + "minor": 0, + "patch": 1, + "prerelease": None, + }, + "version": "0.0.1", }, - "version": "0.0.1", }, } diff --git a/tests/test_flask_restx.py b/tests/test_flask_restx.py index 1a042fb..06a7e57 100644 --- a/tests/test_flask_restx.py +++ b/tests/test_flask_restx.py @@ -85,16 +85,18 @@ def test_changelog_endpoint_with_file(tmpdir): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "release_date": "2018-05-31", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0", }, - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0", }, "1.0.1": { "fixed": [ @@ -103,29 +105,33 @@ def test_changelog_endpoint_with_file(tmpdir): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "2018-05-31", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/compare/v1.0.0...v1.0.1", }, - "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-04-10", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, - "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, } diff --git a/tests/test_non_standard_changelog.py b/tests/test_non_standard_changelog.py index 27272d7..25147da 100644 --- a/tests/test_non_standard_changelog.py +++ b/tests/test_non_standard_changelog.py @@ -83,16 +83,18 @@ def test_changelog_with_versions_and_all_categories(changelog): "changed": ["Release note 1.", "Release note 2."], "deprecated": ["Deprecated feature 1", "Future removal 2"], "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "august 28, 2019", "removed": ["Deprecated feature 2", "Future removal 1"], "security": ["Known issue 1", "Known issue 2"], - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "august 28, 2019", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { @@ -102,14 +104,16 @@ def test_changelog_with_versions_and_all_categories(changelog): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "release_date": "may 03, 2018", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "may 03, 2018", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, }, }, "1.0.1": { @@ -119,26 +123,30 @@ def test_changelog_with_versions_and_all_categories(changelog): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "may 01, 2018", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "may 01, 2018", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, }, }, "1.0.0": { "deprecated": ["Known issue 1 (1.0.0)", "Known issue 2 (1.0.0)"], - "release_date": "2017-01-01", - "version": "1.0.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-01-01", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, }, }, } @@ -146,7 +154,9 @@ def test_changelog_with_versions_and_all_categories(changelog): def test_changelog_with_unreleased_versions_and_all_categories(changelog): assert keepachangelog.to_dict(changelog, show_unreleased=True) == { - "master": {"release_date": None, "version": "master"}, + "master": { + "metadata": {"release_date": None, "version": "master"}, + }, "1.2.0": { "added": [ "Enhancement 1", @@ -157,16 +167,18 @@ def test_changelog_with_unreleased_versions_and_all_categories(changelog): "changed": ["Release note 1.", "Release note 2."], "deprecated": ["Deprecated feature 1", "Future removal 2"], "fixed": ["Bug fix 1", "sub bug 1", "sub bug 2", "Bug fix 2"], - "release_date": "august 28, 2019", "removed": ["Deprecated feature 2", "Future removal 1"], "security": ["Known issue 1", "Known issue 2"], - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "august 28, 2019", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { @@ -176,14 +188,16 @@ def test_changelog_with_unreleased_versions_and_all_categories(changelog): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "release_date": "may 03, 2018", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "may 03, 2018", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, }, }, "1.0.1": { @@ -193,26 +207,30 @@ def test_changelog_with_unreleased_versions_and_all_categories(changelog): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "may 01, 2018", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "may 01, 2018", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, }, }, "1.0.0": { "deprecated": ["Known issue 1 (1.0.0)", "Known issue 2 (1.0.0)"], - "release_date": "2017-01-01", - "version": "1.0.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-01-01", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, }, }, } @@ -244,14 +262,16 @@ def test_raw_changelog_with_versions_and_all_categories(changelog): - Deprecated feature 2 - Future removal 1 """, - "release_date": "august 28, 2019", - "version": "1.2.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 2, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "august 28, 2019", + "version": "1.2.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 2, + "patch": 0, + "prerelease": None, + }, }, }, "1.1.0": { @@ -261,14 +281,16 @@ def test_raw_changelog_with_versions_and_all_categories(changelog): - sub enhancement 2 - Enhancement 2 (1.1.0) """, - "release_date": "may 03, 2018", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "may 03, 2018", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, }, }, "1.0.1": { @@ -278,14 +300,16 @@ def test_raw_changelog_with_versions_and_all_categories(changelog): - sub bug 2 - Bug fix 2 (1.0.1) """, - "release_date": "may 01, 2018", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "may 01, 2018", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, }, }, "1.0.0": { @@ -293,14 +317,16 @@ def test_raw_changelog_with_versions_and_all_categories(changelog): - Known issue 1 (1.0.0) - Known issue 2 (1.0.0) """, - "release_date": "2017-01-01", - "version": "1.0.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-01-01", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, }, }, } diff --git a/tests/test_starlette.py b/tests/test_starlette.py index 7641aa9..0517fef 100644 --- a/tests/test_starlette.py +++ b/tests/test_starlette.py @@ -84,16 +84,18 @@ def test_changelog_endpoint_with_file(tmpdir): "sub enhancement 2", "Enhancement 2 (1.1.0)", ], - "release_date": "2018-05-31", - "version": "1.1.0", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 1, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.1.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 1, + "patch": 0, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0", }, - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0", }, "1.0.1": { "fixed": [ @@ -102,29 +104,33 @@ def test_changelog_endpoint_with_file(tmpdir): "sub bug 2", "Bug fix 2 (1.0.1)", ], - "release_date": "2018-05-31", - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "metadata": { + "release_date": "2018-05-31", + "version": "1.0.1", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 1, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/compare/v1.0.0...v1.0.1", }, - "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": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 0, - "prerelease": None, + "metadata": { + "release_date": "2017-04-10", + "version": "1.0.0", + "semantic_version": { + "buildmetadata": None, + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": None, + }, + "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, - "url": "https://github.test_url/test_project/releases/tag/v1.0.0", }, } From 0584bac2c124e547cb6b7800da145beaa9611881 Mon Sep 17 00:00:00 2001 From: Colin-b Date: Thu, 27 May 2021 16:05:10 +0200 Subject: [PATCH 8/8] Release version 2.0.0.dev0 today --- CHANGELOG.md | 5 ++++- keepachangelog/version.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83de539..7be4b51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [2.0.0.dev0] - 2021-05-27 ### Fixed - `keepachangelog.to_dict` now contains releases that have a URL but no section. - `keepachangelog.to_raw_dict` now contains releases that have a URL but no section. @@ -71,7 +73,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/v1.0.0...HEAD +[Unreleased]: https://github.com/Colin-b/keepachangelog/compare/v2.0.0.dev0...HEAD +[2.0.0.dev0]: https://github.com/Colin-b/keepachangelog/compare/v1.0.0...v2.0.0.dev0 [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 diff --git a/keepachangelog/version.py b/keepachangelog/version.py index 09fdcc6..d21e8e5 100644 --- a/keepachangelog/version.py +++ b/keepachangelog/version.py @@ -3,4 +3,4 @@ # Major should be incremented in case there is a breaking change. (eg: 2.5.8 -> 3.0.0) # Minor should be incremented in case there is an enhancement. (eg: 2.5.8 -> 2.6.0) # Patch should be incremented in case there is a bug fix. (eg: 2.5.8 -> 2.5.9) -__version__ = "1.0.0" +__version__ = "2.0.0.dev0"