check for updates and optionally upgrade packages via pip
#!/usr/bin/env python3 | |
""" | |
check for updates and optionally upgrade packages via pip | |
""" | |
import os | |
import subprocess | |
import sys | |
import termios | |
import tty | |
_trace = lambda x: print(f'$ {x} [cwd={os.getcwd()}]', file=sys.stderr) or x | |
_kw = dict(shell=True, executable='/bin/bash') | |
_fmt = lambda a: _trace(' '.join(map(str, a))) | |
co = lambda *a: subprocess.check_output(_fmt(a), **_kw).decode('utf-8').strip() | |
cc = lambda *a: subprocess.check_call(_fmt(a), **_kw) | |
def getch(): | |
fd = sys.stdin.fileno() | |
old = termios.tcgetattr(fd) | |
try: | |
tty.setraw(fd) | |
val = sys.stdin.read(1).lower() | |
if val == '\x03': | |
sys.exit(1) | |
else: | |
return val | |
except KeyboardInterrupt: | |
sys.exit(1) | |
finally: | |
termios.tcsetattr(fd, termios.TCSADRAIN, old) | |
def pip_checks(): | |
checks = co('pip check || echo failed: $?').splitlines() | |
failed = (checks[-1].startswith('failed: ') | |
and len(checks[-1].split()) == 2 | |
and checks[-1].split()[1].isdigit()) | |
if failed: | |
gits = co('pip freeze').splitlines() | |
gits = {x.split('egg=')[-1] | |
.split('&')[0] | |
.replace('-', '_') | |
for x in gits | |
if 'egg=' in x} | |
checks = {x.split()[0].replace('-', '_') | |
for x in checks[:-1]} | |
return checks - gits | |
else: | |
return [] | |
def pip_packages(): | |
pip = os.environ.get('pip', 'pip') | |
for outdated in co(pip, 'list --outdated').splitlines()[2:]: | |
try: | |
name, old, new, kind, location = outdated.split() | |
print('skip:', name, location) | |
continue | |
except ValueError: | |
name, old, new, kind = outdated.split() | |
print('upgrade:', name, old, '->', new) | |
yield name | |
if __name__ == '__main__': | |
packages = list(pip_packages()) | |
if packages: | |
print('\nwould you like to proceed? y/n\n') | |
assert getch() == 'y', 'abort' | |
cc('pip install --upgrade', *packages) | |
else: | |
print('nothing to upgrade') | |
for package in pip_checks(): | |
cc('pip install', package) | |
checks = pip_checks() | |
if checks: | |
print('error: pip check failed', file=sys.stderr) | |
print('\n'.join(checks)) | |
sys.exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment