Last active
February 11, 2022 10:18
-
-
Save ingvaldlorentzen/d58fe2843069cee9c524d28c12c6eb13 to your computer and use it in GitHub Desktop.
Get Outdated Dependencies pyproject.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import os | |
import subprocess | |
import requests | |
from tomlkit.toml_file import TOMLFile | |
# Hosted on: https://gist.github.com/ingvaldlorentzen/d58fe2843069cee9c524d28c12c6eb13 | |
# Raw: https://gist.githubusercontent.com/ingvaldlorentzen/d58fe2843069cee9c524d28c12c6eb13/raw/update_pyproject.py | |
# Get outdated packages from Poetry | |
poetry_outdated = subprocess.run( | |
['poetry', 'show', '-o', '--no-ansi'], check=True, stdout=subprocess.PIPE | |
).stdout.decode('utf-8') | |
print(poetry_outdated) | |
# Read pyproject package info and format into pure simple python objects with roundtrip to json | |
pyproject_toml = TOMLFile('pyproject.toml') | |
pyproject_toml_data = pyproject_toml.read() | |
# Sort TOML items except python which should be at top | |
pyproject_dependencies = dict(sorted(list(pyproject_toml_data['tool']['poetry']['dependencies'].items()))) | |
python = pyproject_dependencies.pop('python') | |
pyproject_dependencies = { | |
'python': python, | |
**pyproject_dependencies, | |
} | |
pyproject_toml_data['tool']['poetry']['dependencies'] = pyproject_dependencies | |
pyproject_toml_data['tool']['poetry']['dev-dependencies'] = dict( | |
sorted(list(pyproject_toml_data['tool']['poetry']['dev-dependencies'].items())) | |
) | |
if pyproject_toml_data['tool'].get('pipeline', {}).get('ignored-outdated-dependencies', {}): | |
pyproject_toml_data['tool']['pipeline']['ignored-outdated-dependencies'] = dict( | |
sorted(list(pyproject_toml_data['tool']['pipeline']['ignored-outdated-dependencies'].items())) | |
) | |
# Format toml info into pure simple python objects with roundtrip to json | |
pyproject_plain = json.loads(str(pyproject_toml_data.value).replace("'", '"')) | |
pyproject_dependencies = pyproject_plain['tool']['poetry']['dependencies'] | |
pyproject_dev_dependencies = pyproject_plain['tool']['poetry']['dev-dependencies'] | |
ignored_outdated_dependencies = pyproject_plain['tool']['pipeline']['ignored-outdated-dependencies'] | |
# Format shell output into python objects | |
outdated_packages = [ | |
{ | |
'package': line.split()[0], | |
'current_version': line.split()[2 if os.environ.get('CI') else 1], | |
'new_version': line.split()[3 if os.environ.get('CI') else 2], # In CI there is a (!) column for some reason | |
} | |
for line in poetry_outdated.split('\n') | |
if line and line.split()[0] | |
] | |
# Format pyproject package info to same format as poetry output | |
pyproject_packages = [ | |
{'package': key, 'type': 'dependencies', 'version': value if type(value) is str else value['version']} | |
for key, value in pyproject_dependencies.items() | |
] | |
pyproject_dev_packages = [ | |
{'package': key, 'type': 'dev-dependencies', 'version': value if type(value) is str else value['version']} | |
for key, value in pyproject_dev_dependencies.items() | |
] | |
pyproject_packages_combined = pyproject_packages + pyproject_dev_packages | |
# Filter out outdated packages that are not top-level defined dependencies and add info on ignore packages | |
filtered_outdated_packages = [ | |
{ | |
**outdated_package, | |
'reason': ignored_outdated_dependencies.get(outdated_package['package']) or '', | |
'type': 'ignored' | |
if ignored_outdated_dependencies.get(outdated_package['package']) | |
else next( | |
package['type'] | |
for package in pyproject_packages_combined | |
if package['package'] == outdated_package['package'] | |
), | |
} | |
for outdated_package in outdated_packages | |
if outdated_package['package'] in [package['package'] for package in pyproject_packages_combined] | |
] | |
# Write updates to pyproject.toml | |
for outdated_package in filtered_outdated_packages: | |
if outdated_package['type'] != 'ignored': | |
pyproject_package = pyproject_toml_data['tool']['poetry'][outdated_package['type']] | |
if isinstance(pyproject_package[outdated_package['package']], str): | |
pyproject_package[outdated_package['package']] = outdated_package['new_version'] | |
else: | |
pyproject_package[outdated_package['package']]['version'] = outdated_package['new_version'] | |
pyproject_toml.write(pyproject_toml_data) | |
for outdated_package in filtered_outdated_packages: | |
response = requests.get(f"https://pypi.org/pypi/{outdated_package['package']}/json").json()['info'] | |
outdated_package['home_page'] = response['home_page'] | |
outdated_package['package_url'] = response['package_url'] | |
outdated_package['project_urls'] = response['project_urls'] or {} | |
# Write updates to json file for easy MR description parsing in later stage | |
with open('updates.json', 'w') as file: | |
json.dump(filtered_outdated_packages, file, indent=2) | |
file.write('\n') | |
file.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment