From 38e4e086a973c1511100cb193b6ece318dfcf965 Mon Sep 17 00:00:00 2001 From: Andrey Khrolenok Date: Wed, 23 Sep 2020 02:02:56 +0300 Subject: [PATCH] Remaster project structure --- .github/workflows/release.yml | 66 ++++++ .github/workflows/semantic_release.yml | 53 ----- .pre-commit-config.yaml | 6 +- {script => bin}/bootstrap | 0 {script => bin}/dev-deploy | 0 bin/gen_releasenotes | 225 ++++++++++++++++++++ script/run-in-env.sh => bin/run-in-env | 0 {script => bin}/setup | 0 {script => bin}/update | 0 bin/update_requirements | 59 ++++++ custom_components/iaquk/const.py | 2 +- custom_components/iaquk/manifest.json | 21 +- requirements-dev.txt | 2 + script/__init__.py | 1 - script/version_bump.py | 276 ------------------------- 15 files changed, 366 insertions(+), 345 deletions(-) create mode 100644 .github/workflows/release.yml delete mode 100644 .github/workflows/semantic_release.yml rename {script => bin}/bootstrap (100%) rename {script => bin}/dev-deploy (100%) create mode 100755 bin/gen_releasenotes rename script/run-in-env.sh => bin/run-in-env (100%) rename {script => bin}/setup (100%) rename {script => bin}/update (100%) create mode 100755 bin/update_requirements delete mode 100755 script/__init__.py delete mode 100755 script/version_bump.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b66e271 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,66 @@ +--- +name: "Release" + +on: + push: + branches: + - master + +jobs: + release_zip_file: + name: "Prepare release asset" + runs-on: ubuntu-latest + steps: + - name: "Check out repository" + uses: actions/checkout@v1 + + - working-directory: ./custom_components + run: | + echo "::set-env name=package::`ls -F | grep \/$ | sed -n "s/\///g;1p"`" + echo "::set-env name=release_version::`git describe --abbrev=0 | sed s/v//`" + - working-directory: ./custom_components + run: | + echo "::set-env name=basedir::`pwd`/${{ env.package }}" + + - name: "Setup Git" + run: | + git config --global user.name "release" + git config --global user.email "release@GitHub" + + - name: "Set version number" + working-directory: ./custom_components/${{ env.package }} + run: | + sed -i '/VERSION = /c\VERSION = "${{ env.release_version }}"' __init__.py + sed -i '/VERSION = /c\VERSION = "${{ env.release_version }}"' const.py + + - name: "Zip component dir" + working-directory: ./custom_components/${{ env.package }} + run: | + zip ${{ env.package }}.zip -r ./ + - name: "Upload zip to release" + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ${{ env.basedir }}/${{ env.package }}.zip + asset_name: ${{ env.package }}.zip + tag: ${{ env.release_version }} + overwrite: true + + releasenotes: + name: "Prepare releasenotes" + runs-on: ubuntu-latest + steps: + - name: "Check out repository" + uses: actions/checkout@v1 + + - name: "Set up Python 3.7" + uses: actions/setup-python@v2 + with: + python-version: 3.7 + + - name: "Install requirements" + run: | + python3 -m pip install setuptools wheel + python3 -m pip install -r ./requirements-dev.txt + - name: "Update release notes" + run: python3 ./bin/gen_releasenotes --token ${{ secrets.GITHUB_TOKEN }} --repo ${{ github.repository }} --release `git describe --abbrev=0` diff --git a/.github/workflows/semantic_release.yml b/.github/workflows/semantic_release.yml deleted file mode 100644 index 9334ef0..0000000 --- a/.github/workflows/semantic_release.yml +++ /dev/null @@ -1,53 +0,0 @@ ---- -name: semantic_release - -on: - push: - branches: - - master - -jobs: - deploy: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - with: - ref: master - - name: Set up Python 3.7 - uses: actions/setup-python@v1 - with: - python-version: 3.7 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install python-semantic-release - - name: Setup Git - run: | - git config --global user.name "semantic-release" - git config --global user.email "semantic-release@GitHub" - - name: Publish with semantic-release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - DEBUG='*' semantic-release publish - # Pack the ha-iaquk dir as a zip and upload to the release - - name: Zip iaquk dir - run: | - cd /home/runner/work/ha-iaquk/ha-iaquk/custom_components/iaquk - zip iaquk.zip -r ./ - - name: Set release variable - run: | - echo "::set-env name=release_version::`git describe --abbrev=0`" - - name: Sleep - # add delay so upload does not kill the release notes from semantic-release - run: | - sleep 5 - - name: Upload zip to release - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: /home/runner/work/ha-iaquk/ha-iaquk/custom_components/iaquk/iaquk.zip - asset_name: iaquk.zip - tag: ${{ env.release_version }} - overwrite: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ce3fdde..d2c7baa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ repos: args: - --safe - --quiet - files: ^(custom_components|script)/.+\.py$ + files: ^custom_components/.+\.py$ - repo: https://gitlab.com/pycqa/flake8 rev: 3.8.1 hooks: @@ -19,7 +19,7 @@ repos: additional_dependencies: - flake8-docstrings==1.5.0 - pydocstyle==5.0.2 - files: ^(custom_components)/.+\.py$ + files: ^custom_components/.+\.py$ - repo: https://github.com/pre-commit/pre-commit-hooks rev: v2.5.0 hooks: @@ -38,7 +38,7 @@ repos: # shell. - id: mypy name: mypy - entry: script/run-in-env.sh mypy + entry: bin/run-in-env mypy language: script types: [python] require_serial: true diff --git a/script/bootstrap b/bin/bootstrap similarity index 100% rename from script/bootstrap rename to bin/bootstrap diff --git a/script/dev-deploy b/bin/dev-deploy similarity index 100% rename from script/dev-deploy rename to bin/dev-deploy diff --git a/bin/gen_releasenotes b/bin/gen_releasenotes new file mode 100755 index 0000000..006ed50 --- /dev/null +++ b/bin/gen_releasenotes @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 +"""Helper script to generate release notes.""" +import argparse +import logging +import os +import re +import subprocess +from datetime import datetime +from typing import List + +from github import Github, Repository, Tag +from packaging.version import Version + +# http://docs.python.org/2/howto/logging.html#library-config +# Avoids spurious error messages if no logger is configured by the user +logging.getLogger(__name__).addHandler(logging.NullHandler()) + +logging.basicConfig(level=logging.CRITICAL) + +_LOGGER = logging.getLogger(__name__) + +VERSION = "1.1.1" + +ROOT = os.path.dirname(os.path.abspath(f"{__file__}/..")) + +BODY = """ +[![Downloads for this release](https://img.shields.io/github/downloads/{repo}/{version}/total.svg)](https://github.com/{repo}/releases/{version}) + +{changes} + +## Links + +- [If you like what I (@limych) do please consider sponsoring me on Patreon](https://www.patreon.com/join/limych?) +""" + +CHANGE = "- [{line}]({link}) @{author}\n" +NOCHANGE = "_No changes in this release._" + + +def get_commits(repo: Repository, since: datetime, until: datetime): + """Get commits in repo.""" + develop_sha = repo.get_branch("develop").commit.sha + commits = repo.get_commits(sha=develop_sha, since=since, until=until) + if len(list(commits)) == 1: + return [] + return reversed(list(commits)[:-1]) + + +def get_release_tags(repo: Repository) -> List[Tag.Tag]: + """Get list of all release tags from repository.""" + reg = re.compile( + r"^v?[0-9]+\.[0-9]+\.[0-9]+" + r"(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+)?$" + ) + tags = list(filter(lambda tag: re.match(reg, tag.name), list(repo.get_tags()))) + tags.sort(key=lambda x: x.name.lstrip("v"), reverse=True) + _LOGGER.debug("Found tags: %s", tags) + return tags + + +def get_period(repo: Repository, release: str = None) -> List[datetime]: + """Return time period for release notes.""" + data = [datetime.now()] + dateformat = "%a, %d %b %Y %H:%M:%S GMT" + found = release is None + for tag in get_release_tags(repo): + commit = repo.get_commit(tag.commit.sha) + timestamp = datetime.strptime(commit.last_modified, dateformat) + _LOGGER.debug("Process tag %s => timestamp %s", tag.name, timestamp) + data.append(timestamp) + if found: + break + if release is not None and release == tag.name: + found = True + return list(reversed(data[-2:])) + + +def gen_changes(repo: Repository, tag: str = None) -> str: + """Generate list of commits.""" + changes = "" + period = get_period(repo, tag) + _LOGGER.debug("Period: %s", period) + + commits = get_commits(repo, period[0], period[1]) + for commit in commits: + msg = repo.get_git_commit(commit.sha).message + if "\n" in msg: + msg = msg.split("\n")[0] + if ( + "Bump version " in msg + or "Merge branch " in msg + or "Merge tag " in msg + or "Merge pull request " in msg + ): + continue + changes += CHANGE.format( + line=msg, link=commit.html_url, author=commit.author.login + ) + + return changes if changes != "" else NOCHANGE + + +def _bump_release(release, bump_type): + """Bump a release tuple consisting of 3 numbers.""" + major, minor, patch = release + + if bump_type == "patch": + patch += 1 + elif bump_type == "minor": + minor += 1 + patch = 0 + + return major, minor, patch + + +def bump_version(version: Version) -> Version: + """Return a new version given a current version and action.""" + to_change = {} + + # Convert 0.67.3 to 0.67.4 + # Convert 0.67.3.b5 to 0.67.3 + # Convert 0.67.3.dev0 to 0.67.3 + to_change["dev"] = None + to_change["pre"] = None + + if not version.is_prerelease: + to_change["release"] = _bump_release(version.release, "patch") + + temp = Version("0") + temp._version = version._version._replace( # pylint: disable=protected-access + **to_change + ) + return Version(str(temp)) + + +def main(): + """Execute script.""" + parser = argparse.ArgumentParser( + description=f"Release notes generator. Version {VERSION}" + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + help="Enable debugging output.", + ) + parser.add_argument( + "-n", + "--dry-run", + "--dryrun", + action="store_true", + help="Preview release notes generation without running it.", + ) + parser.add_argument( + "--token", + help="Github token to access to repository.", + # required=True, + ) + parser.add_argument( + "--repo", + help="Github repository (default: %(default)s).", + default=subprocess.run( + ["git", "config", "--get", "remote.origin.url"], + stdout=subprocess.PIPE, + check=True, + ) + .stdout.decode("UTF-8") + .replace("https://github.com/", "") + .replace(".git", "") + .strip(), + ) + parser.add_argument( + "--release", + help="Github release tag to update release notes.", + ) + arguments = parser.parse_args() + + if arguments.verbose: + _LOGGER.setLevel(logging.DEBUG) + + if arguments.dry_run: + _LOGGER.debug("Dry run mode ENABLED") + print("!!! Dry Run !!!") + + github = Github(arguments.token) + _LOGGER.debug("Repo: %s", arguments.repo) + repo = github.get_repo(arguments.repo) + if arguments.release is None: + changes = gen_changes(repo) + _LOGGER.debug(changes) + if changes != NOCHANGE: + version = Version(get_release_tags(repo)[0].name.lstrip("v")) + _LOGGER.debug(version) + new_version = bump_version(version) + _LOGGER.debug(new_version) + print( + "Generated release notes for v{version}:\n{message}".format( + version=new_version, + message=changes, + ) + ) + else: + print("Not enough changes for a release.") + else: + version = arguments.release.replace("refs/tags/", "") + _LOGGER.debug("Release tag: %s", version) + msg = BODY.format( + repo=arguments.repo, + version=version, + changes=gen_changes(repo, version), + ) + if arguments.dry_run: + print("Generated release notes:\n" + msg) + else: + release = repo.get_release(version) + release.update_release( + name=version, + prerelease=release.prerelease, + draft=release.draft, + message=msg, + ) + + +if __name__ == "__main__": + main() diff --git a/script/run-in-env.sh b/bin/run-in-env similarity index 100% rename from script/run-in-env.sh rename to bin/run-in-env diff --git a/script/setup b/bin/setup similarity index 100% rename from script/setup rename to bin/setup diff --git a/script/update b/bin/update similarity index 100% rename from script/update rename to bin/update diff --git a/bin/update_requirements b/bin/update_requirements new file mode 100755 index 0000000..67f3b81 --- /dev/null +++ b/bin/update_requirements @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +"""Helper script to update requirements.""" +import json +import os + +import requests + +ROOT = os.path.dirname(os.path.abspath(f"{__file__}/..")) + +PKG_PATH = PACKAGE = None +for current_path, dirs, _ in os.walk(f"{ROOT}/custom_components"): + if current_path.find("__pycache__") != -1: + continue + for dname in dirs: + if dname != "__pycache__": + PACKAGE = dname +PKG_PATH = f"{ROOT}/custom_components/{PACKAGE}" + + +def get_package(requre: str) -> str: + """Extract package name from requirement.""" + return requre.split(">")[0].split("<")[0].split("!")[0].split("=")[0].split("~")[0] + + +harequire = [] +request = requests.get( + "https://raw.githubusercontent.com/home-assistant/home-assistant/dev/setup.py" +) +request = request.text.split("REQUIRES = [")[1].split("]")[0].split("\n") +for req in request: + if "=" in req: + harequire.append(get_package(req.split('"')[1])) + +print(harequire) + +with open(f"{PKG_PATH}/manifest.json") as manifest: + manifest = json.load(manifest) + requirements = [] + for req in manifest["requirements"]: + requirements.append(get_package(req)) + manifest["requirements"] = requirements +with open(f"{ROOT}/requirements.txt") as requirements: + tmp = requirements.readlines() + requirements = [] + for req in tmp: + requirements.append(req.replace("\n", "")) +for req in requirements: + pkg = get_package(req) + if pkg in manifest["requirements"]: + manifest["requirements"].remove(pkg) + manifest["requirements"].append(req) + +for req in manifest["requirements"]: + pkg = get_package(req) + if pkg in harequire: + print(f"{pkg} in HA requirements, no need here.") +print(json.dumps(manifest["requirements"], indent=4, sort_keys=True)) +with open(f"{PKG_PATH}/manifest.json", "w") as manifestfile: + manifestfile.write(json.dumps(manifest, indent=4, sort_keys=True)) diff --git a/custom_components/iaquk/const.py b/custom_components/iaquk/const.py index 5ff3f75..6ca4047 100644 --- a/custom_components/iaquk/const.py +++ b/custom_components/iaquk/const.py @@ -2,7 +2,7 @@ # Base component constants DOMAIN = "iaquk" -VERSION = '1.3.3' +VERSION = "dev" ISSUE_URL = "https://github.com/Limych/ha-iaquk/issues" ATTRIBUTION = None diff --git a/custom_components/iaquk/manifest.json b/custom_components/iaquk/manifest.json index de2f6a1..922d305 100644 --- a/custom_components/iaquk/manifest.json +++ b/custom_components/iaquk/manifest.json @@ -1,12 +1,11 @@ { - "domain": "iaquk", - "name": "IAQ UK", - "documentation": "https://github.com/Limych/ha-iaquk", - "dependencies": [], - "config_flow": false, - "codeowners": [ - "@Limych" - ], - "requirements": [ - ] -} + "codeowners": [ + "@Limych" + ], + "config_flow": false, + "dependencies": [], + "documentation": "https://github.com/Limych/ha-iaquk", + "domain": "iaquk", + "name": "IAQ UK", + "requirements": [] +} \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt index 41900e2..97029cf 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,9 @@ black flake8 mypy +packaging~=20.4 pre-commit +PyGithub==1.53 pylint pylint-strict-informational pyupgrade diff --git a/script/__init__.py b/script/__init__.py deleted file mode 100755 index da52cab..0000000 --- a/script/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Development support scripts.""" diff --git a/script/version_bump.py b/script/version_bump.py deleted file mode 100755 index 3254308..0000000 --- a/script/version_bump.py +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/env python3 -"""Helper script to bump the current version.""" -import argparse -import logging -import os -import sys -from datetime import datetime -import re -import subprocess - -from packaging.version import Version - -# http://docs.python.org/2/howto/logging.html#library-config -# Avoids spurious error messages if no logger is configured by the user -logging.getLogger(__name__).addHandler(logging.NullHandler()) - -# logging.basicConfig(level=logging.DEBUG) - -_LOGGER = logging.getLogger(__name__) - -VERSION = "1.1.2" - -ROOT = os.path.dirname(os.path.abspath(f"{__file__}/..")) - -sys.path.append(ROOT) - - -def fallback_version(localpath): - """Return version from regex match.""" - for fname in ("__init__", "const"): - fpath = f"{localpath}/{fname}.py" - if os.path.isfile(fpath): - with open(fpath) as local: - ret = re.compile(r"^\b(VERSION|__version__)\s*=\s*['\"](.*)['\"]") - for line in local.readlines(): - matcher = ret.match(line) - if matcher: - return str(matcher.group(2)) - return "" - - -def get_package_version(localpath, package): - """Return the local version if any.""" - _LOGGER.debug("Started for %s (%s)", localpath, package) - return_value = "" - if os.path.isfile(f"{localpath}/__init__.py"): - try: - name = "__version__" - return_value = getattr(__import__(f"..{package}", fromlist=[name]), name) - except Exception as err: # pylint: disable=broad-except - _LOGGER.debug(str(err)) - if return_value == "": - try: - name = "VERSION" - return_value = getattr( - __import__(f"..{package}", fromlist=[name]), name - ) - except Exception as err: # pylint: disable=broad-except - _LOGGER.debug(str(err)) - if return_value == "": - return_value = fallback_version(localpath) - _LOGGER.debug(str(return_value)) - assert return_value, "Version not found!" - return return_value - - -def _bump_release(release, bump_type): - """Bump a release tuple consisting of 3 numbers.""" - major, minor, patch = release - - if bump_type == "patch": - patch += 1 - elif bump_type == "minor": - minor += 1 - patch = 0 - - return major, minor, patch - - -def bump_version(version, bump_type): - """Return a new version given a current version and action.""" - to_change = {} - - if bump_type == "minor": - # Convert 0.67.3 to 0.68.0 - # Convert 0.67.3.b5 to 0.68.0 - # Convert 0.67.3.dev0 to 0.68.0 - # Convert 0.67.0.b5 to 0.67.0 - # Convert 0.67.0.dev0 to 0.67.0 - to_change["dev"] = None - to_change["pre"] = None - - if not version.is_prerelease or version.release[2] != 0: - to_change["release"] = _bump_release(version.release, "minor") - - elif bump_type == "patch": - # Convert 0.67.3 to 0.67.4 - # Convert 0.67.3.b5 to 0.67.3 - # Convert 0.67.3.dev0 to 0.67.3 - to_change["dev"] = None - to_change["pre"] = None - - if not version.is_prerelease: - to_change["release"] = _bump_release(version.release, "patch") - - elif bump_type == "dev": - # Convert 0.67.3 to 0.67.4.dev0 - # Convert 0.67.3.b5 to 0.67.4.dev0 - # Convert 0.67.3.dev0 to 0.67.3.dev1 - if version.is_devrelease: - to_change["dev"] = ("dev", version.dev + 1) - else: - to_change["pre"] = ("dev", 0) - to_change["release"] = _bump_release(version.release, "minor") - - elif bump_type == "beta": - # Convert 0.67.5 to 0.67.6b0 - # Convert 0.67.0.dev0 to 0.67.0b0 - # Convert 0.67.5.b4 to 0.67.5b5 - - if version.is_devrelease: - to_change["dev"] = None - to_change["pre"] = ("b", 0) - - elif version.is_prerelease: - if version.pre[0] == "a": - to_change["pre"] = ("b", 0) - if version.pre[0] == "b": - to_change["pre"] = ("b", version.pre[1] + 1) - else: - to_change["pre"] = ("b", 0) - to_change["release"] = _bump_release(version.release, "patch") - - else: - to_change["release"] = _bump_release(version.release, "patch") - to_change["pre"] = ("b", 0) - - elif bump_type == "nightly": - # Convert 0.70.0d0 to 0.70.0d20190424, fails when run on non dev release - if not version.is_devrelease: - raise ValueError("Can only be run on dev release") - - to_change["dev"] = ( - "dev", - datetime.utcnow().date().isoformat().replace("-", ""), - ) - - else: - assert False, f"Unsupported type: {bump_type}" - - temp = Version("0") - temp._version = version._version._replace( # pylint: disable=protected-access - **to_change - ) - return Version(str(temp)) - - -def write_version(package_path, version, dry_run=False): - """Update custom component constant file with new version.""" - for suffix in ("__init__", "const"): - file_path = f"{package_path}/{suffix}.py" - _LOGGER.debug("Try to change %s", file_path) - - with open(file_path) as fil: - cur_content = content = fil.read() - - content = re.sub(r"\nVERSION = .*\n", f"\nVERSION = '{version}'\n", content) - content = re.sub( - r"\n__version__ = .*\n", f"\n__version__ = '{version}'\n", content - ) - - if cur_content != content: - _LOGGER.debug("%s changed", file_path) - if dry_run: - print("%s could was changed." % os.path.basename(file_path)) - else: - with open(file_path, "wt") as fil: - fil.write(content) - - -def main(): - """Execute script.""" - parser = argparse.ArgumentParser( - description=f"Bump version of Python package. Version {VERSION}" - ) - parser.add_argument( - "type", - help="The type of the bump the version to.", - choices=["beta", "dev", "patch", "minor", "nightly"], - ) - parser.add_argument( - "--commit", action="store_true", help="Create a version bump commit." - ) - parser.add_argument( - "package_dir", nargs="?", default=None, help="The path to package." - ) - parser.add_argument( - "--dry-run", - action="store_true", - help="Preview version bumping without running it.", - ) - arguments = parser.parse_args() - - if arguments.dry_run: - print("!!! Dry Run !!! No Files Was Changed") - - # pylint: disable=subprocess-run-check - if arguments.commit and subprocess.run(["git", "diff", "--quiet"]).returncode == 1: - print("Cannot use --commit because git is dirty.") - return - - if arguments.package_dir is not None: - package_dir = os.path.abspath(arguments.package_dir) - package = package_dir.split("/")[-1] - else: - package = None - for current_path, dirs, _ in os.walk(f"{ROOT}/custom_components"): - if current_path.find("__pycache__") != -1: - continue - for dname in dirs: - if dname != "__pycache__": - package = dname - - assert package, "Component not found!" - package_dir = f"{ROOT}/custom_components/{package}" - package = f"custom_components.{package}" - - current = Version(get_package_version(package_dir, package)) - bumped = bump_version(current, arguments.type) - assert bumped > current, "BUG! New version is not newer than old version" - - if arguments.dry_run: - print(f"Current version: {current}\n" f" New version: {bumped}") - - write_version(package_dir, bumped, arguments.dry_run) - - if not arguments.commit or arguments.dry_run: - return - - subprocess.run(["git", "commit", "-nam", f"Bump version to {bumped}"]) - - -# pylint: disable=import-outside-toplevel -def test_bump_version(): - """Make sure it all works.""" - import pytest - - assert bump_version(Version("0.56.0"), "beta") == Version("0.56.1b0") - assert bump_version(Version("0.56.0b3"), "beta") == Version("0.56.0b4") - assert bump_version(Version("0.56.0.dev0"), "beta") == Version("0.56.0b0") - - assert bump_version(Version("0.56.3"), "dev") == Version("0.57.0.dev0") - assert bump_version(Version("0.56.0b3"), "dev") == Version("0.57.0.dev0") - assert bump_version(Version("0.56.0.dev0"), "dev") == Version("0.56.0.dev1") - - assert bump_version(Version("0.56.3"), "patch") == Version("0.56.4") - assert bump_version(Version("0.56.3.b3"), "patch") == Version("0.56.3") - assert bump_version(Version("0.56.0.dev0"), "patch") == Version("0.56.0") - - assert bump_version(Version("0.56.0"), "minor") == Version("0.57.0") - assert bump_version(Version("0.56.3"), "minor") == Version("0.57.0") - assert bump_version(Version("0.56.0.b3"), "minor") == Version("0.56.0") - assert bump_version(Version("0.56.3.b3"), "minor") == Version("0.57.0") - assert bump_version(Version("0.56.0.dev0"), "minor") == Version("0.56.0") - assert bump_version(Version("0.56.2.dev0"), "minor") == Version("0.57.0") - - today = datetime.utcnow().date().isoformat().replace("-", "") - assert bump_version(Version("0.56.0.dev0"), "nightly") == Version( - f"0.56.0.dev{today}" - ) - with pytest.raises(ValueError): - assert bump_version(Version("0.56.0"), "nightly") - - -if __name__ == "__main__": - main()