Skip to content

Commit

Permalink
Merge pull request #5 from brainelectronics/feature/update-package-ve…
Browse files Browse the repository at this point in the history
…rsion-automatically

Update package version automatically
  • Loading branch information
brainelectronics authored Jul 24, 2022
2 parents 62cee49 + 02c8e7c commit 3e3923c
Show file tree
Hide file tree
Showing 8 changed files with 336 additions and 3 deletions.
45 changes: 45 additions & 0 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Upload Python Package

on:
push:
branches:
- develop

permissions:
contents: read

jobs:
deploy:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
if [ -f requirements-deploy.txt ]; then pip install -r requirements-deploy.txt; fi
- name: Build package
run: |
python update_version.py \
--changelog_file changelog.md \
--version_file nextion/version.py \
--debug
python setup.py sdist
- name: Publish package
uses: pypa/gh-action-pypi-publish@717ba43cfbb0387f6ce311b169a825772f54d295
with:
user: __token__
# password: ${{ secrets.PYPI_API_TOKEN }}
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
repository_url: https://test.pypi.org/legacy/
skip_existing: true
print_hash: true
verbose: true
20 changes: 19 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed
### Fixed
-->
<!--
RegEx for release version from file
r"^\#\# \[\d{1,}[.]\d{1,}[.]\d{1,}\] \- \d{4}\-\d{2}-\d{2}$"
-->

## Released
## [0.4.0] - 2022-07-24
### Added
- `clearChannel(channel)` in [`nextion_waveform`](nextion/nextion_waveform.py)
to clear a waveform channel data
- Script to [update version file](update_version.py) based on changelog entry
- [Requirements file](requirements-deploy.txt) for GitHub CI python publish
workflow
- [GitHub CI python publish workflow](.github/workflows/python-publish.yml)

### Fixed
- Replace undefined `__author__` in [`setup.py`](setup.py)
- Add missing shebang header to [`version`](nextion/version.py) file

## [0.3.0] - 2022-07-22
### Added
- Function `hide()` and `show()` for all supported Nextion elements to hide
Expand Down Expand Up @@ -51,8 +68,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Example HMI file](examples/everything.HMI) to be used for all examples

<!-- Links -->
[Unreleased]: https://github.com/brainelectronics/micropython-nextion/compare/0.3.0...develop
[Unreleased]: https://github.com/brainelectronics/micropython-nextion/compare/0.4.0...develop

[0.4.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.4.0
[0.3.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.3.0
[0.2.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.2.0
[0.1.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.1.0
Expand Down
8 changes: 8 additions & 0 deletions examples/waveform/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@
s0.addValue(2, channel_2_value)
s0.addValue(3, channel_3_value)
time.sleep(0.1)
print()

time.sleep(1)

# remove channel 0 waveform
print('Removing channel 0 waveform...')
s0.clearChannel(0)
print()

print('Returning to REPL in 5 seconds')

Expand Down
18 changes: 18 additions & 0 deletions nextion/nextion_waveform.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,21 @@ def addValue(self, ch: int, number: int) -> bool:
cmd = "add {},{},{}".format(self.cid, ch, number)
self._nh.sendCommand(cmd)
return True

def clearChannel(self, ch: int) -> bool:
"""
Clear a channel of the waveform
:param ch: The channel to clear or 255 for all channels
:type ch: int
:returns: True on success, false otherwise
:rtype: bool
"""
if (ch > 3) and (ch != 255):
self._logger.debug("Only channel (0-3) or all (255) can be cleared")
return False

cmd = "cle {},{}".format(self.cid, ch)
self._nh.sendCommand(cmd)
return self._nh.recvRetCommandFinished()
5 changes: 4 additions & 1 deletion nextion/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
__version_info__ = ('0', '2', '0')
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

__version_info__ = ('0', '4', '0')
__version__ = '.'.join(__version_info__)
__author__ = 'brainelectronics'
14 changes: 14 additions & 0 deletions requirements-deploy.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# List external packages here
# Avoid fixed versions
# # to upload package to PyPi or other package hosts
# twine>=4.0.1,<5

# to parse changelog semver
semver>=2.13.0,<3

# # to convert markdown to reStructuredText
# m2rr>=0.2.3,<1
# # fix bug in m2rr dependecy definitions
# # see https://github.com/qhua948/m2rr/pull/1
# docutils<=0.18
# mistune<=1
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
long_description=long_description,
long_description_content_type='text/markdown',
url='https://github.com/brainelectronics/micropython-nextion',
author=__author__,
author='brainelectronics',
author_email='info@brainelectronics.de',
classifiers=[
'Development Status :: 4 - Beta',
Expand Down
227 changes: 227 additions & 0 deletions update_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

"""
Update version info in python version file with latest changelog version
The changelog and package version shall always be aligned. This script can be
used to update the version info line "__version_info__ = ..." of a version.py
file with the latest changelog entry.
This changelog entry shall follow the semantic version pattern, see
https://semver.org/ and shall match the following pattern:
## [x.y.z] - yyyy-mm-dd
The line shall start with two hashtags followed by a single space. The semver
with x, y and z as non-negative integers, seperated by a dot and surrounded by
square brackets. Followed by a space, a dash, another space and the ISO8601
formatted date. Additional timestamps after the data, seperated from the date
by a single space, are optional.
"""

__author__ = "brainelectronics"
__copyright__ = "MIT License, Copyright (c) 2022 brainelectronics"
__credits__ = ["brainelectronics"]
__version__ = "0.1.0"
__maintainer__ = "brainelectronics"
__email__ = "git@brainelectronics.de"
__status__ = "Beta"

import argparse
import fileinput
import logging
from pathlib import Path
import re
import semver
from sys import stdout


def parser_valid_file(parser: argparse.ArgumentParser, arg: str) -> str:
"""
Determine whether file exists.
:param parser: The parser
:type parser: parser object
:param arg: The file to check
:type arg: str
:raise argparse.ArgumentError: Argument is not a file
:returns: Input file path, parser error is thrown otherwise.
:rtype: str
"""
if not Path(arg).is_file():
parser.error("The file {} does not exist!".format(arg))
else:
return arg


def parse_arguments() -> argparse.Namespace:
"""
Parse CLI arguments.
:raise argparse.ArgumentError Argparse error
:return: argparse object
"""
parser = argparse.ArgumentParser(description="""
Update version info file based on changelog entry
""", formatter_class=argparse.ArgumentDefaultsHelpFormatter)

# default arguments
parser.add_argument('-d', '--debug',
action='store_true',
help='Output logger messages to stderr')

# specific arguments
parser.add_argument('--changelog_file',
dest='changelog_file',
required=True,
type=lambda x: parser_valid_file(parser, x),
help='Path to changelog file')

parser.add_argument('--version_file',
dest='version_file',
required=True,
type=lambda x: parser_valid_file(parser, x),
help='Path to version file')

parsed_args = parser.parse_args()

return parsed_args


def parse_changelog(changelog_file: Path, logger: logging.Logger) -> str:
"""
Parse the changelog for the first matching release version line
:param changelog_file: The path to the changelog file
:type changelog_file: Path
:param logger: Logger object
:type logger: logging.Logger
:returns: Extracted semantic version string
:rtype: str
"""
release_version_line_regex = r"^\#\# \[\d{1,}[.]\d{1,}[.]\d{1,}\] \- \d{4}\-\d{2}-\d{2}"
# append "$" to match only ISO8601 dates without additional timestamps
release_version_line = ""

with open(changelog_file, "r") as f:
for line in f:
match = re.search(release_version_line_regex, line)
if match:
release_version_line = match.group()
break

logger.debug("First matching release version line: '{}'".
format(release_version_line))

return parse_semver_line(release_version_line, logger)


def parse_semver_line(release_version_line: str,
logger: logging.Logger) -> str:
"""
Parse a release version line for a semantic version
:param release_version_line: The release version line as described
:type release_version_line: str
:param logger: Logger object
:type logger: logging.Logger
:returns: Semantic version string
:rtype: str
"""
# release_version_line = "## [0.2.0] - 2022-05-19"
semver_regex = r"\[\d{1,}[.]\d{1,}[.]\d{1,}\]"
semver_string = "0.0.0"

# extract semver from release version line
match = re.search(semver_regex, release_version_line)
if match:
semver_string = match.group()
# remove '[' and ']' from semver_string
semver_string = re.sub(r"[\[\]]", "", semver_string)
if not semver.VersionInfo.isvalid(semver_string):
logger.error("Parsed SemVer string is invalid, check format")
raise ValueError("Invalid SemVer string")
logger.debug("Extracted SemVer string: '{}'".format(semver_string))
else:
logger.warning("No SemVer string found in given release version line")

# semver_string = "0.2.0"
return semver_string


def create_version_info_line(semver_string: str,
logger: logging.Logger) -> str:
"""
Create the version info line used in "version.py"
:param semver_string: The valid semver string
:type semver_string: str
:param logger: Logger object
:type logger: logging.Logger
:returns: Complete version info line
:rtype: str
"""
# semver_string = "0.2.0"
ver = semver.VersionInfo.parse(semver_string)

version_info = (str(ver.major), str(ver.minor), str(ver.patch))
version_info_line = "__version_info__ = {}".format(version_info)
logger.debug("New version info line: '{}'".format(version_info_line))

# version_info_line = "__version_info__ = ('0', '2', '0')"
return version_info_line


def update_version_file(version_file: Path,
version_info_line: str,
logger: logging.Logger) -> None:
"""
Update the version file with a new version info line
:param version_file: The path to the version file
:type version_file: Path
:param version_info_line: The version info line
:type version_info_line: str
:param logger: Logger object
:type logger: logging.Logger
"""
# standard output (print) is redirected to the original file
for line in fileinput.input(version_file, inplace=True):
if line.startswith("__version_info__ = "):
print(version_info_line, end="\n")
else:
# keep line ending
print(line, end="")

logger.debug("Version file '{}' updated with '{}'".
format(version_file, version_info_line))


def main():
# parse CLI arguments
args = parse_arguments()

custom_format = '[%(asctime)s] [%(levelname)-8s] [%(filename)-15s @'\
' %(funcName)-15s:%(lineno)4s] %(message)s'
logging.basicConfig(level=logging.INFO,
format=custom_format,
stream=stdout)
logger = logging.getLogger(__name__)
if args.debug:
logger.setLevel(logging.DEBUG)

here = Path(__file__).parent
changelog_file = (here / args.changelog_file).resolve()
version_file = (here / args.version_file).resolve()

logger.debug("Using changelog file '{}' to update version file '{}'".
format(changelog_file, version_file))

semver_string = parse_changelog(changelog_file, logger)
version_info_line = create_version_info_line(semver_string, logger)
update_version_file(version_file, version_info_line, logger)


if __name__ == '__main__':
main()

0 comments on commit 3e3923c

Please sign in to comment.