From de279a6227f81604b661470a89e535dc97b7e323 Mon Sep 17 00:00:00 2001 From: Nex Sabre Date: Tue, 25 May 2021 21:53:00 +0200 Subject: [PATCH 1/5] Get latest version from the pypi.org (can be handy with GitHub Actions usage) --- bump.py | 25 ++++++++++++++++++++++--- setup.py | 3 ++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/bump.py b/bump.py index 60fdce5..69e6e89 100644 --- a/bump.py +++ b/bump.py @@ -1,6 +1,8 @@ import re import sys +import requests + try: import configparser except ImportError: # 2.7 @@ -11,6 +13,7 @@ from packaging.utils import canonicalize_version pattern = re.compile(r"((?:__)?version(?:__)? ?= ?[\"'])(.+?)([\"'])") +name_pattern = re.compile(r"((?:__)?name(?:__)? ?= ?[\"'])(.+?)([\"'])") class SemVer(object): @@ -62,7 +65,7 @@ def parse(cls, version): ) def bump( - self, major=False, minor=False, patch=False, pre=None, local=None, reset=False + self, major=False, minor=False, patch=False, pre=None, local=None, reset=False ): if major: self.major += 1 @@ -94,6 +97,20 @@ def find_version(input_string): return match[1] +def find_name(input_string): + match = first(name_pattern.findall(input_string)) + if match is None: + raise NoVersionFound + return match[1] + + +def get_latest_version(name): + response = requests.get( + "https://pypi.org/pypi/{}/json".format(name) + ).json() + return response["info"]["version"] + + @click.command() @click.option( "--major", @@ -132,10 +149,10 @@ def find_version(input_string): @click.option( "--canonicalize", flag_value=True, default=None, help="Canonicalize the new version" ) +@click.option("--pypi", flag_value=True, default=None, help="Get latest version from pypi.org") @click.argument("input", type=click.File("rb"), default=None, required=False) @click.argument("output", type=click.File("wb"), default=None, required=False) -def main(input, output, major, minor, patch, reset, pre, local, canonicalize): - +def main(input, output, major, minor, patch, reset, pre, local, canonicalize, pypi): config = configparser.RawConfigParser() config.read([".bump", "setup.cfg"]) @@ -150,6 +167,8 @@ def main(input, output, major, minor, patch, reset, pre, local, canonicalize): contents = input.read().decode("utf-8") try: version_string = find_version(contents) + if pypi: + version_string = get_latest_version(find_name(contents)) except NoVersionFound: click.echo("No version found in ./{}.".format(input.name)) sys.exit(1) diff --git a/setup.py b/setup.py index 23f3998..cc8bcf2 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name="bump", - version="1.3.0", + version="1.3.1", description="Bumps package version numbers", long_description=open("README.rst").read(), license="MIT", @@ -28,6 +28,7 @@ "configparser ; python_version<'3'", "first", "packaging>=17.1", + "requests" ], entry_points={"console_scripts": ["bump = bump:main"]}, ) From e5f8fe14ee3230483f914b768f44775fc609231d Mon Sep 17 00:00:00 2001 From: Nex Sabre Date: Tue, 25 May 2021 21:56:06 +0200 Subject: [PATCH 2/5] . --- bump.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/bump.py b/bump.py index 69e6e89..b175a61 100644 --- a/bump.py +++ b/bump.py @@ -12,7 +12,7 @@ from first import first from packaging.utils import canonicalize_version -pattern = re.compile(r"((?:__)?version(?:__)? ?= ?[\"'])(.+?)([\"'])") +version_pattern = re.compile(r"((?:__)?version(?:__)? ?= ?[\"'])(.+?)([\"'])") name_pattern = re.compile(r"((?:__)?name(?:__)? ?= ?[\"'])(.+?)([\"'])") @@ -64,9 +64,7 @@ def parse(cls, version): major=int(major), minor=int(minor), patch=int(patch), pre=pre, local=local ) - def bump( - self, major=False, minor=False, patch=False, pre=None, local=None, reset=False - ): + def bump(self, major=False, minor=False, patch=False, pre=None, local=None, reset=False): if major: self.major += 1 if reset: @@ -90,8 +88,12 @@ class NoVersionFound(Exception): pass +class NoNameFound(Exception): + pass + + def find_version(input_string): - match = first(pattern.findall(input_string)) + match = first(version_pattern.findall(input_string)) if match is None: raise NoVersionFound return match[1] @@ -100,7 +102,7 @@ def find_version(input_string): def find_name(input_string): match = first(name_pattern.findall(input_string)) if match is None: - raise NoVersionFound + raise NoNameFound return match[1] @@ -178,7 +180,7 @@ def main(input, output, major, minor, patch, reset, pre, local, canonicalize, py version_string = str(version) if canonicalize: version_string = canonicalize_version(version_string) - new = pattern.sub("\g<1>{}\g<3>".format(version_string), contents) + new = version_pattern.sub("\g<1>{}\g<3>".format(version_string), contents) output.write(new.encode()) click.echo(version_string) From bb82751f6958155349a269fbfadb3f25f6e97ede Mon Sep 17 00:00:00 2001 From: Nex Sabre Date: Tue, 25 May 2021 21:58:29 +0200 Subject: [PATCH 3/5] Update README and bump version --- README.rst | 1 + setup.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 75be0ca..e587426 100644 --- a/README.rst +++ b/README.rst @@ -50,6 +50,7 @@ the pre-release identifier or local version segment:: --pre TEXT Set the pre-release identifier --local TEXT Set the local version segment --canonicalize Canonicalize the new version + --pypi Get latest information about version from pypi.org --help Show this message and exit. The `--reset` option should be used alongside with minor or major bump. diff --git a/setup.py b/setup.py index cc8bcf2..2df691c 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name="bump", - version="1.3.1", + version="1.4.0", description="Bumps package version numbers", long_description=open("README.rst").read(), license="MIT", From ea97948d921b28e449d55629e5dc059178ba5520 Mon Sep 17 00:00:00 2001 From: Nex Sabre Date: Tue, 25 May 2021 22:07:56 +0200 Subject: [PATCH 4/5] Use black to make reformat --- bump.py | 12 +++++++----- setup.py | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/bump.py b/bump.py index b175a61..905d3df 100644 --- a/bump.py +++ b/bump.py @@ -64,7 +64,9 @@ def parse(cls, version): major=int(major), minor=int(minor), patch=int(patch), pre=pre, local=local ) - def bump(self, major=False, minor=False, patch=False, pre=None, local=None, reset=False): + def bump( + self, major=False, minor=False, patch=False, pre=None, local=None, reset=False + ): if major: self.major += 1 if reset: @@ -107,9 +109,7 @@ def find_name(input_string): def get_latest_version(name): - response = requests.get( - "https://pypi.org/pypi/{}/json".format(name) - ).json() + response = requests.get("https://pypi.org/pypi/{}/json".format(name)).json() return response["info"]["version"] @@ -151,7 +151,9 @@ def get_latest_version(name): @click.option( "--canonicalize", flag_value=True, default=None, help="Canonicalize the new version" ) -@click.option("--pypi", flag_value=True, default=None, help="Get latest version from pypi.org") +@click.option( + "--pypi", flag_value=True, default=None, help="Get latest version from pypi.org" +) @click.argument("input", type=click.File("rb"), default=None, required=False) @click.argument("output", type=click.File("wb"), default=None, required=False) def main(input, output, major, minor, patch, reset, pre, local, canonicalize, pypi): diff --git a/setup.py b/setup.py index 2df691c..030ebc5 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ "configparser ; python_version<'3'", "first", "packaging>=17.1", - "requests" + "requests", ], entry_points={"console_scripts": ["bump = bump:main"]}, ) From 7efdb479ee7ae41f2a20978ed76ead26473fb664 Mon Sep 17 00:00:00 2001 From: Nex Sabre Date: Wed, 26 May 2021 17:18:38 +0200 Subject: [PATCH 5/5] Add a condition not to bump the version if the local version is higher than the published version --- bump.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/bump.py b/bump.py index 905d3df..3532e71 100644 --- a/bump.py +++ b/bump.py @@ -113,6 +113,18 @@ def get_latest_version(name): return response["info"]["version"] +def compare_version(local_version, pypi_version): + from packaging import version + + if local_version == pypi_version: + return local_version, False + return ( + (local_version, True) + if version.parse(local_version) > version.parse(pypi_version) + else (pypi_version, False) + ) + + @click.command() @click.option( "--major", @@ -169,10 +181,22 @@ def main(input, output, major, minor, patch, reset, pre, local, canonicalize, py canonicalize = canonicalize or config.get("bump", "canonicalize", fallback=False) contents = input.read().decode("utf-8") + lock = False try: version_string = find_version(contents) if pypi: - version_string = get_latest_version(find_name(contents)) + pypi_version = get_latest_version(find_name(contents)) + version_string, lock = compare_version( + version_string, get_latest_version(find_name(contents)) + ) + if lock: + click.echo( + "Local version is higher: {} > {}.\nLooks like bump was done manually.".format( + version_string, pypi_version + ) + ) + sys.exit(0) + except NoVersionFound: click.echo("No version found in ./{}.".format(input.name)) sys.exit(1)