You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
3.3 KiB
115 lines
3.3 KiB
#!/usr/bin/env python |
|
""" check requirements.txt for outdated packages """ |
|
|
|
import pathlib |
|
|
|
import requests |
|
|
|
|
|
class Requirements: |
|
"""handle requirements.txt""" |
|
|
|
FILE_PATH = "tubearchivist/requirements.txt" |
|
LOCK = "/tmp/tubearchivist-requirements.lock" |
|
|
|
def __init__(self): |
|
self.exists = self.checked_today() |
|
self.all_requirements = False |
|
self.all_updates = False |
|
|
|
def checked_today(self): |
|
"""skip requirements check when lock file exists""" |
|
exists = pathlib.Path(self.LOCK).exists() |
|
return exists |
|
|
|
def look_for_updates(self): |
|
"""look through requirements and check for updates""" |
|
self.all_requirements = self.get_dependencies() |
|
self.all_updates = self.check_packages() |
|
|
|
def get_dependencies(self): |
|
"""read out requirements.txt""" |
|
|
|
all_requirements = [] |
|
with open(self.FILE_PATH, "r", encoding="utf-8") as f: |
|
dependencies = f.readlines() |
|
|
|
for dependency in dependencies: |
|
package, version = dependency.split("==") |
|
all_requirements.append((package, version.strip())) |
|
|
|
all_requirements.sort(key=lambda x: x[0].lower()) |
|
|
|
return all_requirements |
|
|
|
def check_packages(self): |
|
"""compare installed with remote version""" |
|
|
|
total = len(self.all_requirements) |
|
print(f"checking versions for {total} packages...") |
|
|
|
all_updates = {} |
|
|
|
for dependency in self.all_requirements: |
|
package, version_installed = dependency |
|
url = f"https://pypi.org/pypi/{package}/json" |
|
response = requests.get(url).json() |
|
version_remote = response["info"]["version"] |
|
homepage = response["info"]["home_page"] |
|
if version_remote != version_installed: |
|
to_update = { |
|
package: {"from": version_installed, "to": version_remote} |
|
} |
|
all_updates.update(to_update) |
|
message = ( |
|
f"update {package} {version_installed}" |
|
+ f"==> {version_remote}\n {homepage}" |
|
) |
|
print(message) |
|
|
|
if not all_updates: |
|
print("no updates found") |
|
|
|
# remember that |
|
pathlib.Path(self.LOCK).touch() |
|
|
|
return all_updates |
|
|
|
def apply_updates(self): |
|
"""update requirements.txt file with new versions""" |
|
|
|
to_write = [] |
|
|
|
for requirement in self.all_requirements: |
|
package, old_version = requirement |
|
|
|
if package in self.all_updates.keys(): |
|
package_version = self.all_updates[package]["to"] |
|
else: |
|
package_version = old_version |
|
|
|
to_write.append(f"{package}=={package_version}\n") |
|
|
|
with open(self.FILE_PATH, "w", encoding="utf-8") as f: |
|
f.writelines(to_write) |
|
|
|
print("requirements.txt updates") |
|
|
|
|
|
def main(): |
|
"""main to check for updates""" |
|
handler = Requirements() |
|
if handler.exists: |
|
return |
|
|
|
handler.look_for_updates() |
|
if handler.all_updates: |
|
input_response = input("\nupdate requirements.txt? [y/n] ") |
|
if input_response == "y": |
|
handler.apply_updates() |
|
else: |
|
print("skip update...") |
|
|
|
|
|
if __name__ == "__main__": |
|
main()
|
|
|