mirror of
https://github.com/YunoHost-Apps/django-for-runners_ynh.git
synced 2024-09-03 18:26:16 +02:00
9117c6de27
Download and setup missing Python versions using eGenix PyRun from: https://github.com/eGenix/egenix-pyrun/
151 lines
4 KiB
Python
Executable file
151 lines
4 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
"""
|
|
Download and setup missing Python versions using eGenix PyRun from:
|
|
|
|
https://github.com/eGenix/egenix-pyrun/
|
|
"""
|
|
|
|
import dataclasses
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tarfile
|
|
import urllib.request
|
|
from argparse import ArgumentParser
|
|
from pathlib import Path
|
|
from pprint import pprint
|
|
|
|
from urllib3.util import parse_url
|
|
|
|
|
|
DEFAULT_VERSION = '3.11'
|
|
|
|
|
|
GET_PIP_URL = 'https://bootstrap.pypa.io/get-pip.py' # https://github.com/eGenix/egenix-pyrun/issues/11
|
|
|
|
|
|
@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"
|
|
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 setup_pyrun(*, pyrun_version: str, destination: str):
|
|
print('_' * 100)
|
|
dest_path = Path(destination).expanduser()
|
|
dest_path.mkdir(parents=True, exist_ok=True)
|
|
print(f'Setup pyrun for Python {pyrun_version} to: {dest_path}')
|
|
|
|
release_info = get_pyrun_release_info()
|
|
pprint(release_info)
|
|
|
|
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:
|
|
sys.exit(0)
|
|
|
|
url = release_info.get(version=pyrun_version)
|
|
if not url:
|
|
print(f'No PyRun release found for Python {pyrun_version}')
|
|
sys.exit(1)
|
|
|
|
print(f'Download {url}')
|
|
|
|
subprocess.check_call(
|
|
['wget', '--timestamp', url],
|
|
cwd=dest_path,
|
|
)
|
|
|
|
filename = Path(parse_url(url).path).name
|
|
print(f'{filename=}')
|
|
tgz_path = dest_path / filename
|
|
assert tgz_path.is_file(), f'{tgz_path=}'
|
|
|
|
final_path = dest_path / f'pyrun{pyrun_version}/'
|
|
print(f'Extract {tgz_path} to {final_path}...')
|
|
final_path.mkdir(parents=False, exist_ok=True)
|
|
with tarfile.open(tgz_path, "r:gz") as tgz_file:
|
|
for member in tgz_file.getmembers():
|
|
if ".." in member.name or member.name.startswith("/"):
|
|
raise ValueError(f"Unsafe file path detected: {member.name}")
|
|
tgz_file.extractall(path=final_path)
|
|
|
|
tgz_path.unlink()
|
|
|
|
pyrun_bin = final_path / 'bin' / f'pyrun{pyrun_version}'
|
|
|
|
print(f'Install pip/virtualenv for Python {pyrun_version}')
|
|
# FIXME: # https://github.com/eGenix/egenix-pyrun/issues/11
|
|
subprocess.check_call(
|
|
['wget', '--timestamp', GET_PIP_URL],
|
|
cwd=dest_path,
|
|
)
|
|
get_pip_path = dest_path / 'get-pip.py'
|
|
|
|
subprocess.check_call(
|
|
[pyrun_bin, get_pip_path],
|
|
)
|
|
get_pip_path.unlink()
|
|
subprocess.check_call(
|
|
[pyrun_bin, '-m', 'pip', 'install', '-U', 'virtualenv'],
|
|
)
|
|
print('\n')
|
|
|
|
print(f'Check {pyrun_bin}:')
|
|
subprocess.check_call([pyrun_bin, '-V'])
|
|
|
|
print('\n')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
parser = ArgumentParser(description='Setup PyRun for a specific Python version.')
|
|
parser.add_argument(
|
|
'--version',
|
|
type=str,
|
|
default=DEFAULT_VERSION,
|
|
help=f'Python version to setup with PyRun (default: {DEFAULT_VERSION}),',
|
|
)
|
|
parser.add_argument(
|
|
'--destination',
|
|
type=str,
|
|
help=f'Destination path to store PyRun (e.g.: ~/.local/)',
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
setup_pyrun(
|
|
pyrun_version=args.version,
|
|
destination=args.destination,
|
|
)
|