Skip to content

Commit

Permalink
Merge pull request #17 from brainelectronics/feature/parse-changelog-…
Browse files Browse the repository at this point in the history
…to-json
  • Loading branch information
brainelectronics authored Oct 26, 2022
2 parents 2663266 + 0f3af96 commit 2bdec36
Show file tree
Hide file tree
Showing 8 changed files with 628 additions and 21 deletions.
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,15 @@ Create version info files based on the latest changelog entry.
- [Available default template files](#available-default-template-files)
- [C header file](#c-header-file)
- [Python package file](#python-package-file)
- [JSON output](#json-output)
- [Console](#console)
- [File](#file)
- [Advanced](#advanced)
- [Custom regular expressions](#custom-regular-expressions)
- [Custom template file](#custom-template-file)
- [Additional version info content](#additional-version-info-content)
- [Contributing](#contributing)
- [Unittests](#unittests)
- [Credits](#credits)

<!-- /MarkdownTOC -->
Expand Down Expand Up @@ -105,6 +110,36 @@ __version__ = '.'.join(__version_info__)
```

#### JSON output

The additional, optional argument `--pretty` will output the JSON data with an
indentation of 4 in order to provide the data in an easy to read format.

##### Console

```bash
changelog2version \
--changelog_file changelog.md \
--print \
--debug
```

```json
{"info": {"version": "0.6.0"}, "releases": {"0.6.0": [{"upload_time": "2022-10-26"}], "0.5.0": [{"upload_time": "2022-10-20"}], "0.4.0": [{"upload_time": "2022-08-07"}], "0.3.0": [{"upload_time": "2022-08-05"}], "0.2.0": [{"upload_time": "2022-08-03"}], "0.1.1": [{"upload_time": "2022-07-31"}], "0.1.0": [{"upload_time": "2022-07-31"}]}}
```

##### File

```bash
changelog2version \
--changelog_file changelog.md \
--output changelog.json \
--pretty \
--debug
```

See [example JSON file][ref-example-json-file]

## Advanced

### Custom regular expressions
Expand Down Expand Up @@ -202,6 +237,33 @@ __version__ = '.'.join(__version_info__) + '-rc1234'
```

## Contributing

### Unittests

Run the unittests locally with the following command after installing this
package in a virtual environment or by using `tox` to create one on each run.

```bash
# install the package with all its development dependencies
pip install .[dev]

# run all tests
nose2 --config tests/unittest.cfg

# run only one specific tests
nose2 tests.test_extract_version.TestExtractVersion.test_version_line_regex
```

Generate the coverage files with

```bash
python create_report_dirs.py
coverage html
```

The coverage report is placed at `reports/coverage/html/index.html`

## Credits

Based on the [PyPa sample project][ref-pypa-sample]. Also a big thank you to
Expand All @@ -211,6 +273,7 @@ documentation and [regex example][ref-semver-regex-example]
<!-- Links -->
[ref-package-version-file]: src/changelog2version/version.py
[ref-templates-folder]: src/changelog2version/templates
[ref-example-json-file]: examples/changelog.json
[ref-py-core-metadata-spec]: https://packaging.python.org/specifications/core-metadat
[ref-pep440]: https://peps.python.org/pep-0440/
[ref-pypa-sample]: https://github.com/pypa/sampleproject
Expand Down
15 changes: 14 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ r"^\#\# \[\d{1,}[.]\d{1,}[.]\d{1,}\] \- \d{4}\-\d{2}-\d{2}$"
-->

## Released
## [0.6.0] - 2022-10-26
### Added
- Changelog can be parsed as JSON file with a similar format as the pypi
package JSON info available at `https://pypi.org/pypi/PACKAGENAME/json`, see
[#16][ref-issue-16]
The new option `--output` writes the data in JSON valid format to a file specified file, `--print` flag sends the data in JSON valid format to
`sys.stdout`. In both cases `--pretty` flag can be set to output the data with an indentation of 4.

### Changed
- `--version_file` argument is optional in order to allow a JSON output only

## [0.5.0] - 2022-10-20
### Added
- Support additional version info file content in python version files by
Expand Down Expand Up @@ -128,15 +139,17 @@ r"^\#\# \[\d{1,}[.]\d{1,}[.]\d{1,}\] \- \d{4}\-\d{2}-\d{2}$"
- Data folder after fork

<!-- Links -->
[Unreleased]: https://github.com/brainelectronics/changelog2version/compare/0.5.0...develop
[Unreleased]: https://github.com/brainelectronics/changelog2version/compare/0.6.0...develop

[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
[0.3.0]: https://github.com/brainelectronics/changelog2version/tree/0.3.0
[0.2.0]: https://github.com/brainelectronics/changelog2version/tree/0.2.0
[0.1.1]: https://github.com/brainelectronics/changelog2version/tree/0.1.1
[0.1.0]: https://github.com/brainelectronics/changelog2version/tree/0.1.0

[ref-issue-16]: https://github.com/brainelectronics/changelog2version/issues/16
[ref-issue-5]: https://github.com/brainelectronics/changelog2version/issues/5
[ref-issue-8]: https://github.com/brainelectronics/changelog2version/issues/8
[ref-issue-11]: https://github.com/brainelectronics/changelog2version/issues/11
Expand Down
42 changes: 42 additions & 0 deletions examples/changelog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"info": {
"version": "0.6.0"
},
"releases": {
"0.6.0": [
{
"upload_time": "2022-10-26"
}
],
"0.5.0": [
{
"upload_time": "2022-10-20"
}
],
"0.4.0": [
{
"upload_time": "2022-08-07"
}
],
"0.3.0": [
{
"upload_time": "2022-08-05"
}
],
"0.2.0": [
{
"upload_time": "2022-08-03"
}
],
"0.1.1": [
{
"upload_time": "2022-07-31"
}
],
"0.1.0": [
{
"upload_time": "2022-07-31"
}
]
}
}
95 changes: 89 additions & 6 deletions src/changelog2version/extract_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import re
from semver import VersionInfo
from sys import stdout
from typing import Optional
from typing import List, Optional


class ExtractVersionError(Exception):
Expand Down Expand Up @@ -61,6 +61,13 @@ def __init__(self, logger: Optional[logging.Logger] = None):
r"(?P<timestamp>\d{2,}:\d{2,}:\d{2,}?))?" # time as HH:MM:SS
)

self._date_line_regex = (
r".*" # anything
r"(?P<datetime>\d{4}\-\d{2}-\d{2})" # datetime as YYYY-MM-DD
r"(([T ]{1})" # seperation between date and time by "T" or space
r"(?P<timestamp>\d{2,}:\d{2,}:\d{2,}?))?" # time as HH:MM:SS
)

@property
def version_line_regex(self) -> str:
"""
Expand Down Expand Up @@ -109,6 +116,30 @@ def semver_line_regex(self, value: str) -> None:
except re.error:
raise ExtractVersionError("Invalid regex pattern")

@property
def date_line_regex(self) -> str:
"""
Get regex to extract the date part from the complete version line
:returns: Regex to get the date part
:rtype: str
"""
return self._date_line_regex

@date_line_regex.setter
def date_line_regex(self, value: str) -> None:
"""
Set regex to extract the date part from the complete version line
:param value: Regex to get the date part
:type value: str
"""
try:
re.compile(value)
self._date_line_regex = value
except re.error:
raise ExtractVersionError("Invalid regex pattern")

@property
def semver_data(self) -> VersionInfo:
"""
Expand Down Expand Up @@ -173,17 +204,69 @@ def parse_changelog(self, changelog_file: Path) -> str:
"""
release_version_line = ""

release_version_lines = self.parse_changelog_completely(
changelog_file=changelog_file,
first_line_only=True)

if len(release_version_lines) >= 1:
release_version_line = release_version_lines[0]

return release_version_line

def parse_changelog_completely(self,
changelog_file: Path,
first_line_only: bool = False) -> List[str]:
"""
Parse the changelog for all matching version lines
:param changelog_file: The path to the changelog file
:type changelog_file: Path
:param first_line_only: Flag to break after first match found
:type first_line_only: bool
:returns: List of extracted semantic version strings
:rtype: List[str]
"""
release_version_lines = []

with open(changelog_file, "r") as f:
for line in f:
match = re.search(self.version_line_regex, line)
if match:
release_version_line = match.group()
break
release_version_lines.append(match.group())
if first_line_only:
break

self._logger.debug("First matching release version line: '{}'".
format(release_version_line))
self._logger.debug("Matching release version lines: '{}'".
format(release_version_lines))

return release_version_line
return release_version_lines

def parse_semver_line_date(self, release_version_line: str) -> str:
"""
Parse a version line for a valid ISO8601 datetime
Examples of a valid ISO8601 datetime lines:
- "## [0.2.0] - 2022-05-19"
- "## [107.3.18] - 1900-01-01 12:34:56"
- "## [1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay] - 2012-01-02" # noqa
:param release_version_line: The release version line
:type release_version_line: str
:returns: ISO8601 datetime string, e.g. "1970-01-01"
:rtype: str
"""
date_string = "1970-01-01"

match = re.search(self.date_line_regex, release_version_line)
if match:
if len(match.groups()) >= 4 and match.group(2):
date_string = match.group(1) + match.group(2)
else:
date_string = match.group(1)

return date_string

def parse_semver_line(self, release_version_line: str) -> str:
"""
Expand Down
Loading

0 comments on commit 2bdec36

Please sign in to comment.