diff --git a/CHANGELOG.md b/CHANGELOG.md index a33ab6b..7be4b51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [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. + +### 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. +- `keepachangelog.to_dict` now allows to provide any line iterable instead of only a file path. + ## [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. @@ -57,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/README.md b/README.md index 195bb22..d95175e 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) @@ -36,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": [ @@ -54,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", }, } ``` @@ -145,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 @@ -167,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 @@ -184,35 +193,50 @@ 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", }, } ``` +## 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 ce729e3..51a92dd 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, @@ -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,17 +23,15 @@ 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)} + 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: @@ -68,32 +66,110 @@ 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. + + :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. + """ + # Allow for changelog as a file path or as a context manager providing content + try: + with open(changelog_path) as change_log: + return _to_dict(change_log, show_unreleased) + except TypeError: + return _to_dict(changelog_path, show_unreleased) + + +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 = {} - with open(changelog_path) as change_log: - current_release = {} - category = [] - for line in change_log: - line = line.strip(" \n") - - if is_release(line): - current_release = add_release(changes, line, show_unreleased) - 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) - + 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(): - changes.get(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 metadata) and not metadata["release_date"]: + unreleased_version = version + + if not show_unreleased: + changes.pop(unreleased_version, None) 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(): + metadata = current_release["metadata"] + content += f"\n## [{metadata['version'].capitalize()}]" + + if metadata.get("release_date"): + content += f" - {metadata['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 ["metadata", "uncategorized"]: + 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(): + metadata = current_release["metadata"] + if not metadata.get("url"): + continue + + content += f"[{metadata['version'].capitalize()}]: {metadata['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 @@ -104,17 +180,27 @@ 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, {"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 metadata) and not metadata["release_date"]: + unreleased_version = version + + changes.pop(unreleased_version, None) return changes 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/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" 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 59159fe..961be91 100644 --- a/tests/test_changelog.py +++ b/tests/test_changelog.py @@ -1,3 +1,4 @@ +import io import os import os.path @@ -68,7 +69,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 """ @@ -76,21 +78,21 @@ 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"], +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"], + "removed": ["Deprecated feature 2", "Future removal 1"], + "security": ["Known issue 1", "Known issue 2"], + "metadata": { "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, @@ -100,13 +102,15 @@ def test_changelog_with_versions_and_all_categories(changelog): "prerelease": None, }, }, - "1.1.0": { - "changed": [ - "Enhancement 1 (1.1.0)", - "sub enhancement 1", - "sub enhancement 2", - "Enhancement 2 (1.1.0)", - ], + }, + "1.1.0": { + "changed": [ + "Enhancement 1 (1.1.0)", + "sub enhancement 1", + "sub enhancement 2", + "Enhancement 2 (1.1.0)", + ], + "metadata": { "release_date": "2018-05-31", "version": "1.1.0", "semantic_version": { @@ -116,15 +120,23 @@ 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.1": { - "fixed": [ - "Bug fix 1 (1.0.1)", - "sub bug 1", - "sub bug 2", - "Bug fix 2 (1.0.1)", - ], + }, + "1.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": [ + "Bug fix 1 (1.0.1)", + "sub bug 1", + "sub bug 2", + "Bug fix 2 (1.0.1)", + ], + "metadata": { "release_date": "2018-05-31", "version": "1.0.1", "semantic_version": { @@ -136,8 +148,10 @@ def test_changelog_with_versions_and_all_categories(changelog): }, "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)"], + }, + "1.0.0": { + "deprecated": ["Known issue 1 (1.0.0)", "Known issue 2 (1.0.0)"], + "metadata": { "release_date": "2017-04-10", "version": "1.0.0", "semantic_version": { @@ -149,7 +163,21 @@ def test_changelog_with_versions_and_all_categories(changelog): }, "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) == 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): @@ -178,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": { @@ -195,16 +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", + }, + }, + "1.0.2": { + "metadata": { + "version": "1.0.2", + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", }, - "url": "https://github.test_url/test_project/compare/v1.0.1...v1.1.0", }, "1.0.1": { "raw": """### Fixed @@ -213,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 new file mode 100644 index 0000000..3ac2667 --- /dev/null +++ b/tests/test_changelog_no_category.py @@ -0,0 +1,103 @@ +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"], + "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": { + "uncategorized": [ + "Enhancement 1 (1.1.0)", + "sub enhancement 1", + "sub enhancement 2", + "Enhancement 2 (1.1.0)", + ], + "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": { + "uncategorized": [ + "Bug fix 1 (1.0.1)", + "sub bug 1", + "sub bug 2", + "Bug fix 2 (1.0.1)", + ], + "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 11fcdc1..4f2044c 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. @@ -65,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 """ @@ -77,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", @@ -88,57 +92,163 @@ 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", + "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.1...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.1": { - "version": "1.0.1", - "semantic_version": { - "buildmetadata": None, - "major": 1, - "minor": 0, - "patch": 1, - "prerelease": None, + "1.0.2": { + "metadata": { + "url": "https://github.test_url/test_project/compare/v1.0.1...v1.0.2", + "version": "1.0.2", }, - "release_date": "2018-05-31", + }, + "1.0.1": { "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"], + "metadata": { + "release_date": "2017-01-01", + "semantic_version": { + "buildmetadata": None, + "major": 0, + "minor": 0, + "patch": 1, + "prerelease": None, + }, + "version": "0.0.1", + }, }, } + + +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) + +## [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.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 +""" + ) 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", }, }