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 diff --git a/src/changelog2version/extract_version.py b/src/changelog2version/extract_version.py index f53a6e3..a38f4b5 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,30 @@ 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: + latest_description_lines.append(line.strip()) + 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 diff --git a/src/changelog2version/update_version.py b/src/changelog2version/update_version.py index 9052078..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: {}". @@ -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 } diff --git a/tests/test_extract_version.py b/tests/test_extract_version.py index abef1e2..8e83ef5 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,10 +71,37 @@ def test_date_line_regex(self) -> None: self.assertEqual("Invalid regex pattern", str(context.exception)) - @unittest.skip("Not yet implemented") + 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)) + 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"), @@ -97,18 +125,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\n" ), ( "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\n" ), ) 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 +153,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), 3) + @params( # valid semver release version lines ("## [1.2.3] - 2012-01-02", "## [1.2.3] - 2012-01-02"),