Skip to content

Instantly share code, notes, and snippets.

@wasdee
Last active April 19, 2022 02:28
Show Gist options
  • Save wasdee/6021790ff566354f0c2cdc36d0969678 to your computer and use it in GitHub Desktop.
Save wasdee/6021790ff566354f0c2cdc36d0969678 to your computer and use it in GitHub Desktop.
poetry upgrade
from plumbum import ProcessExecutionError, local
from dataclasses import dataclass, field
import re
from tomlkit import parse
poetry = local['poetry']
deps = {}
deps['outdated'] = poetry('show', '--outdated' ).splitlines()
@dataclass
class Dep:
name: str
installed: str
latest: str
description: str
dev: bool = False
extras: list[str] = field(default_factory=list)
@property
def withExtras(self):
return len(self.extras) > 0
@property
def extras_str(self):
if self.withExtras:
return f"[{','.join(self.extras)}]"
else:
return ""
def __hash__(self) -> int:
return hash(self.name)
deps['outdated'] = { Dep(*re.split('\s+', raw_dep, maxsplit=3)) for raw_dep in deps['outdated'] }
with open('pyproject.toml') as f:
pyproject = parse(f.read())
deps['normal'] = pyproject['tool']['poetry']['dependencies']
deps['dev'] = pyproject['tool']['poetry']['dev-dependencies']
deps['all'] = deps['normal'] | deps['dev']
deps['major'] = set(deps['normal'].keys()) | set(deps['dev'].keys())
deps['toUpdate'] = set()
# filter non-major dep and assign dev status
for dep in deps['outdated']:
if dep.name in deps['dev']:
dep.dev = True
if dep.name in deps['major']:
if 'extras' in deps['all'][dep.name]:
dep.extras = deps['all'][dep.name]['extras']
deps['toUpdate'].add(dep)
noDev_deps = [dep for dep in deps['toUpdate'] if not dep.dev]
dev_deps = [dep for dep in deps['toUpdate'] if dep.dev]
deps['updated'] = set()
def update_deps_individual():
print('Updating deps individually...')
for dep in deps['toUpdate']:
print(f'{dep.name}{dep.extras_str} {dep.installed} -> {dep.latest}')
try:
if dep.dev:
poetry('add', f"{dep.name}{dep.extras_str}@latest", '--dev')
else:
poetry('add', f"{dep.name}{dep.extras_str}@latest")
deps['updated'].add(dep)
except ProcessExecutionError as e:
if 'SolverProblemError' in str(e):
print(f'Failed Solver: {dep.name} {dep.installed} -> {dep.latest}')
else:
raise e
def update_deps_together_remove_then_install():
print('Updating deps all together...')
noDev_deps_str = ' '.join([f'{dep.name}' for dep in noDev_deps if dep not in deps['updated']])
dev_deps_str = ' '.join([f'{dep.name}' for dep in dev_deps if dep not in deps['updated']])
try:
if len(noDev_deps_str) > 0:
poetry('remove', *noDev_deps_str)
poetry('add', *noDev_deps_str)
except ProcessExecutionError as e:
if 'SolverProblemError' in str(e):
print(f'Failed Solver: no-dev deps: {noDev_deps_str}')
else:
raise e
try:
if len(dev_deps_str) > 0:
poetry('remove', *dev_deps_str, '--dev')
poetry('add', *dev_deps_str, '--dev')
except ProcessExecutionError as e:
if 'SolverProblemError' in str(e):
print(f'Failed Solver: dev deps: {dev_deps_str}')
else:
raise e
if __name__ == '__main__':
update_deps_individual()
print('')
update_deps_together_remove_then_install()
print('Done!')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment