Last active
August 15, 2024 11:16
-
-
Save jedie/919ce4490e563b67ebec3a88d8b9f076 to your computer and use it in GitHub Desktop.
Python script to install https://github.com/eGenix/egenix-pyrun into '~/.local'
This file contains hidden or 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
#!/bin/python3 | |
""" | |
Download and setup missing Python versions using eGenix PyRun | |
https://github.com/eGenix/egenix-pyrun | |
""" | |
import dataclasses | |
import json | |
import shutil | |
import subprocess | |
import tarfile | |
import urllib.request | |
from pathlib import Path | |
from pprint import pprint | |
from urllib3.util import parse_url | |
PYRUN_VERSIONS = ('3.8', '3.9', '3.10', '3.11', '3.12') | |
LOCAL_BIN_PATH = Path('~/.local').expanduser() | |
@dataclasses.dataclass | |
class ReleaseInfo: | |
version: str | |
urls: list[str] | |
def get(self, *, version): | |
for url in self.urls: | |
if f'-py{version}_' in url: | |
return url | |
def get_pyrun_release_info() -> ReleaseInfo: | |
api_url = "https://api.github.com/repos/eGenix/egenix-pyrun/releases" | |
print(f'Fetch {api_url}...') | |
with urllib.request.urlopen(api_url) as response: | |
data = response.read().decode() | |
releases = json.loads(data) | |
latest_release = releases[0] | |
# pprint(latest_release) | |
print(latest_release['html_url']) | |
print(latest_release['tag_name']) | |
print(latest_release['name']) | |
urls = [] | |
for asset in latest_release['assets']: | |
urls.append(asset['browser_download_url']) | |
return ReleaseInfo(version=latest_release['name'], urls=urls) | |
def pyrun_filter(member, dest_path): | |
if member.name in ('./bin/pyrun', './bin/python3'): | |
# Don't overwrite existing pyrun or python3 | |
return None | |
print(f'Extract {member.name}') | |
return member | |
def setup_pyrun(): | |
release_info = get_pyrun_release_info() | |
pprint(release_info) | |
for pyrun_version in PYRUN_VERSIONS: | |
python_bin_name = f'python{pyrun_version}' | |
path = shutil.which(python_bin_name) | |
if path: | |
path = Path(path).resolve() | |
print(f'Found {python_bin_name} at {path}') | |
print(path.name) | |
if path.name.startswith('pyrun'): | |
print(f'{python_bin_name} is pyrun -> update') | |
else: | |
continue | |
print('_' * 100) | |
print(f'Setup pyrun for Python {pyrun_version}') | |
if url := release_info.get(version=pyrun_version): | |
print(f'Download {url}') | |
download_path = Path('~/bin').expanduser() | |
subprocess.check_call( | |
['wget', '--timestamp', url], | |
cwd=download_path, | |
) | |
filename = Path(parse_url(url).path).name | |
print(f'{filename=}') | |
tgz_path = download_path / filename | |
assert tgz_path.is_file(), f'{tgz_path=}' | |
print(f'Extract {tgz_path} to {LOCAL_BIN_PATH}...') | |
with tarfile.open(tgz_path, "r:gz") as tgz_file: | |
tgz_file.extractall(path=LOCAL_BIN_PATH, filter=pyrun_filter) | |
print('\n') | |
def print_python_versions(): | |
for pyrun_version in PYRUN_VERSIONS: | |
python_bin_name = f'python{pyrun_version}' | |
print(f'{python_bin_name}...', end=' ') | |
if path := shutil.which(python_bin_name): | |
path = Path(path).resolve() | |
print(f'Found at {path}:') | |
subprocess.run([python_bin_name, '-V']) | |
print() | |
else: | |
print('Not found.\n') | |
if __name__ == '__main__': | |
setup_pyrun() | |
print() | |
print_python_versions() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment