Skip to content

Instantly share code, notes, and snippets.

@iddan
Last active October 30, 2017 20:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iddan/22bbb835f7a862a314f995f5d66674eb to your computer and use it in GitHub Desktop.
Save iddan/22bbb835f7a862a314f995f5d66674eb to your computer and use it in GitHub Desktop.
Update python setup.py version safely
import ast
import jedi
from os import path
from pipenv.project import Project
from git import Repo
from git.refs.tag import TagReference
from pkg_resources import get_distribution
class Semver:
def __init__(self, string):
major, minor, patch = map(int, string.split('.'))
self.major = major
self.minor = minor
self.patch = patch
def __str__(self):
return '.'.join(map(str, (self.major, self.minor, self.patch)))
def add(self, part, amount):
setattr(self, part, getattr(self, part) + amount)
return self
def is_setup(source, call):
script = jedi.api.Script(source, call.lineno, call.col_offset)
definition = script.goto_definitions()[-1]
return definition.module_name == 'core' and definition.name == 'setup'
def replace_in_line(line, old, new, string):
lines = string.split('\n')
lines[line] = lines[line].replace(old, new)
return '\n'.join(lines)
def get_setup_version_value_node(source):
for node in ast.walk(ast.parse(source)):
if isinstance(node, ast.Call) and is_setup(source, node):
for keyword in node.keywords:
if keyword.arg == 'version':
return keyword.value
project = Project()
def update_setup_file_version(part, setup_path):
with open(setup_path, 'r+') as setup:
source = setup.read()
value = get_setup_version_value_node(source)
old_version = value.s
new_version = str(Semver(old_version).add(part, 1))
setup.seek(0)
setup.write(replace_in_line(value.lineno - 1, old_version, new_version, source))
setup.truncate()
return new_version
# part = 'major' | 'minor' | 'patch'
def version(part):
setup_path = path.join(project.project_directory, 'setup.py')
if not path.exists(setup_path):
raise NotImplementedError('setup.py must exist')
new_version = update_setup_file_version(part, setup_path)
repo = Repo(project.project_directory)
repo.index.add(['setup.py'])
repo.index.commit(f'v{new_version}')
repo.create_tag(f'v{new_version}', ref=repo.active_branch)
return new_version
if __name__ == "__main__":
import sys
new_version = version(sys.argv[1])
print(new_version)
@iddan
Copy link
Author

iddan commented Oct 30, 2017

requires pipenv and GitPython installed (pip install pipenv GitPython)
usage: python3 version.py patch | minor | major

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment