From a0ee668dda9bbf34854327e4f3ee493043c360c6 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 11 Nov 2022 10:26:21 +0100 Subject: [PATCH 1/9] extract latest description lines from changelog, resolve #19 --- src/changelog2version/extract_version.py | 36 ++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/changelog2version/extract_version.py b/src/changelog2version/extract_version.py index f53a6e3..c9cc209 100644 --- a/src/changelog2version/extract_version.py +++ b/src/changelog2version/extract_version.py @@ -32,6 +32,7 @@ def __init__(self, logger: Optional[logging.Logger] = None): logger = self._create_logger() self._logger = logger self._semver_data = VersionInfo(*(0, 0, 0)) + self._latest_description_lines = [] self._semver_line_regex = ( r"^(?P0|[1-9]\d*)\." # major version part @@ -163,6 +164,26 @@ def semver_data(self, value: VersionInfo) -> None: else: raise ExtractVersionError("Value is not of type VersionInfo") + @property + def latest_description_lines(self) -> List[str]: + """ + Get latest description lines of the parsed changelog + + :returns: Content of latest release + :rtype: List[str] + """ + return self._latest_description_lines + + @property + def latest_description(self) -> str: + """ + Get latest description of the parsed changelog + + :returns: Latest release description + :rtype: str + """ + return '\n'.join(self.latest_description_lines) + @staticmethod def _create_logger(logger_name: str = None) -> logging.Logger: """ @@ -228,17 +249,32 @@ def parse_changelog_completely(self, :rtype: List[str] """ release_version_lines = [] + matches_found = 0 + latest_description_lines = [] with open(changelog_file, "r") as f: for line in f: match = re.search(self.version_line_regex, line) if match: release_version_lines.append(match.group()) + matches_found += 1 + if first_line_only: break + # collect the lines until the next (second) match is found + if matches_found == 1: + stripped_line = line.strip() + if stripped_line: + latest_description_lines.append(stripped_line) + self._logger.debug("Matching release version lines: '{}'". format(release_version_lines)) + self._logger.debug("Latest description lines: '{}'". + format(latest_description_lines[1:])) + + # the version line itself is also included, ignore it + self._latest_description_lines = latest_description_lines[1:] return release_version_lines From d003c0d786ec1bb1fc7d2679ff77aa368072e45f Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 11 Nov 2022 10:26:50 +0100 Subject: [PATCH 2/9] add unittest for latest changelog extraction --- tests/test_extract_version.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/test_extract_version.py b/tests/test_extract_version.py index abef1e2..a467b64 100644 --- a/tests/test_extract_version.py +++ b/tests/test_extract_version.py @@ -97,18 +97,22 @@ def test_parse_changelog_file(self, ( "changelog_with_date.md", ["## [1.3.0] - 2022-10-26", "## [1.2.3] - 2022-07-31"], + "### Added\n- Something fixed" ), ( "changelog_with_date_and_time.md", [ "## [94.0.0] - 2022-10-26 23:59:01", "## [93.10.1] - 2022-07-31 12:34:56" - ] + ], + "### Added\n- Something fixed" ), ) def test_parse_changelog_completely_file(self, file_name: str, - expectation: List[str]) -> None: + expectation: List[str], + expected_description: str + ) -> None: """Test parse_changelog""" changelog = self._here / 'data' / 'valid' / file_name @@ -121,6 +125,13 @@ def test_parse_changelog_completely_file(self, self.assertTrue(all(isinstance(ele, str) for ele in result)) self.assertEqual(expectation, result) + # test extracted description + self.assertIsInstance(self.ev.latest_description, str) + self.assertEqual(self.ev.latest_description, expected_description) + self.assertTrue(all(isinstance(ele, str) + for ele in self.ev.latest_description_lines)) + self.assertEqual(len(self.ev.latest_description_lines), 2) + @params( # valid semver release version lines ("## [1.2.3] - 2012-01-02", "## [1.2.3] - 2012-01-02"), From 9fccd8ba4617d2a92c7d4befa26e29e386a7a622 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 11 Nov 2022 10:27:37 +0100 Subject: [PATCH 3/9] add extracted changelog description to returned JSON in changelog2version call --- src/changelog2version/update_version.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/changelog2version/update_version.py b/src/changelog2version/update_version.py index 9052078..eafb569 100644 --- a/src/changelog2version/update_version.py +++ b/src/changelog2version/update_version.py @@ -253,7 +253,10 @@ def main(): content=version_file_content) changelog_data = { - 'info': {'version': semver_string}, + 'info': { + 'version': semver_string, + 'description': version_extractor.latest_description, + }, 'releases': release_infos } From 70d1043f10aaf8404e85f7fb9003c661e1354df1 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 11 Nov 2022 10:28:23 +0100 Subject: [PATCH 4/9] printed, non debug output of changelog2version is JSON data only --- src/changelog2version/update_version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/changelog2version/update_version.py b/src/changelog2version/update_version.py index eafb569..6653e46 100644 --- a/src/changelog2version/update_version.py +++ b/src/changelog2version/update_version.py @@ -239,8 +239,8 @@ def main(): if version_file_type in template_file_map: template_file = template_file_map[version_file_type] - logger.info("Selected '{}' based on version_file_type: '{}'". - format(template_file, version_file_type)) + logger.debug("Selected '{}' based on version_file_type: '{}'". + format(template_file, version_file_type)) else: raise KeyError("Either specify a custom template file or choose" "a template from this list: {}". From d7a0c1b62190125bd0ca0f30ae784d52d8b196f4 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 11 Nov 2022 10:30:01 +0100 Subject: [PATCH 5/9] add unittest for semver_data property, increase coverage --- tests/test_extract_version.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/test_extract_version.py b/tests/test_extract_version.py index a467b64..769cffd 100644 --- a/tests/test_extract_version.py +++ b/tests/test_extract_version.py @@ -5,6 +5,7 @@ import logging from nose2.tools import params from pathlib import Path +from semver import VersionInfo from sys import stdout from typing import List import unittest @@ -70,6 +71,21 @@ def test_date_line_regex(self) -> None: self.assertEqual("Invalid regex pattern", str(context.exception)) + def test_semver_data(self) -> None: + """Test property semver_data""" + self.assertIsInstance(self.ev.semver_data, VersionInfo) + + valid_semver_data = VersionInfo(*(1, 2, 3)) + self.ev.semver_data = valid_semver_data + self.assertIsInstance(self.ev.semver_data, VersionInfo) + self.assertEqual(self.ev.semver_data, valid_semver_data) + + with self.assertRaises(ExtractVersionError) as context: + self.ev.semver_data = "asdf" + + self.assertEqual("Value is not of type VersionInfo", + str(context.exception)) + @unittest.skip("Not yet implemented") def test__create_logger(self): """Test logger creation""" From e51272dea85a252bf50eb8c278da6e93d4329741 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 11 Nov 2022 10:31:08 +0100 Subject: [PATCH 6/9] add unittest for _create_logger function, increase coverage --- tests/test_extract_version.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/test_extract_version.py b/tests/test_extract_version.py index 769cffd..bedede9 100644 --- a/tests/test_extract_version.py +++ b/tests/test_extract_version.py @@ -86,10 +86,22 @@ def test_semver_data(self) -> None: self.assertEqual("Value is not of type VersionInfo", str(context.exception)) - @unittest.skip("Not yet implemented") def test__create_logger(self): """Test logger creation""" - pass + logger_name = "Test Logger" + named_logger = ExtractVersion._create_logger(logger_name=logger_name) + + self.assertIsInstance(named_logger, logging.Logger) + self.assertEqual(named_logger.name, logger_name) + self.assertEqual(named_logger.level, logging.DEBUG) + self.assertEqual(named_logger.disabled, False) + + logger_without_name = ExtractVersion._create_logger() + + self.assertIsInstance(logger_without_name, logging.Logger) + self.assertEqual(logger_without_name.name, + "changelog2version.extract_version") + self.assertEqual(logger_without_name.level, logging.DEBUG) @params( ("changelog_with_date.md", "## [1.3.0] - 2022-10-26"), From 90544e7d19103367f5cab72cbd2df68e811e2c69 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 11 Nov 2022 10:37:18 +0100 Subject: [PATCH 7/9] update changelog --- changelog.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index ad86492..eef2961 100644 --- a/changelog.md +++ b/changelog.md @@ -17,6 +17,16 @@ r"^\#\# \[\d{1,}[.]\d{1,}[.]\d{1,}\] \- \d{4}\-\d{2}-\d{2}$" --> ## Released +## [0.7.0] - 2022-11-11 +### Added +- Changelog parsed as JSON contains a new key `description` like the PyPi package JSON info, compare to `https://pypi.org/pypi/changelog2version/json`, with the description/content of the latest change, see #19, relates to #18 +- Increase unittest coverage above 95% + +### Changed +- Line breaks are no longer used in this changelog for enumerations +- Issues are referenced as `#123` instead of `[#123][ref-issue-123]` to avoid explicit references at the bottom or some other location in the file +- Output of `changelog2version` call with `--print` but without `--debug` option is JSON compatible + ## [0.6.0] - 2022-10-26 ### Added - Changelog can be parsed as JSON file with a similar format as the pypi @@ -139,8 +149,9 @@ r"^\#\# \[\d{1,}[.]\d{1,}[.]\d{1,}\] \- \d{4}\-\d{2}-\d{2}$" - Data folder after fork -[Unreleased]: https://github.com/brainelectronics/changelog2version/compare/0.6.0...develop +[Unreleased]: https://github.com/brainelectronics/changelog2version/compare/0.7.0...main +[0.7.0]: https://github.com/brainelectronics/changelog2version/tree/0.7.0 [0.6.0]: https://github.com/brainelectronics/changelog2version/tree/0.6.0 [0.5.0]: https://github.com/brainelectronics/changelog2version/tree/0.5.0 [0.4.0]: https://github.com/brainelectronics/changelog2version/tree/0.4.0 From ee2dde5722fcfd3bf298af3f2b045690ba7d5a7b Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 11 Nov 2022 10:53:22 +0100 Subject: [PATCH 8/9] do not remove empty lines of latest description --- src/changelog2version/extract_version.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/changelog2version/extract_version.py b/src/changelog2version/extract_version.py index c9cc209..a38f4b5 100644 --- a/src/changelog2version/extract_version.py +++ b/src/changelog2version/extract_version.py @@ -264,9 +264,7 @@ def parse_changelog_completely(self, # collect the lines until the next (second) match is found if matches_found == 1: - stripped_line = line.strip() - if stripped_line: - latest_description_lines.append(stripped_line) + latest_description_lines.append(line.strip()) self._logger.debug("Matching release version lines: '{}'". format(release_version_lines)) From 5f95372086634fee9aac49c7316ac0e21c48775a Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 11 Nov 2022 11:05:18 +0100 Subject: [PATCH 9/9] fix unittest after allowing empty lines in changelog description --- tests/test_extract_version.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_extract_version.py b/tests/test_extract_version.py index bedede9..8e83ef5 100644 --- a/tests/test_extract_version.py +++ b/tests/test_extract_version.py @@ -125,7 +125,7 @@ def test_parse_changelog_file(self, ( "changelog_with_date.md", ["## [1.3.0] - 2022-10-26", "## [1.2.3] - 2022-07-31"], - "### Added\n- Something fixed" + "### Added\n- Something fixed\n" ), ( "changelog_with_date_and_time.md", @@ -133,7 +133,7 @@ def test_parse_changelog_file(self, "## [94.0.0] - 2022-10-26 23:59:01", "## [93.10.1] - 2022-07-31 12:34:56" ], - "### Added\n- Something fixed" + "### Added\n- Something fixed\n" ), ) def test_parse_changelog_completely_file(self, @@ -158,7 +158,7 @@ def test_parse_changelog_completely_file(self, self.assertEqual(self.ev.latest_description, expected_description) self.assertTrue(all(isinstance(ele, str) for ele in self.ev.latest_description_lines)) - self.assertEqual(len(self.ev.latest_description_lines), 2) + self.assertEqual(len(self.ev.latest_description_lines), 3) @params( # valid semver release version lines