-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpythoninstall.py
More file actions
131 lines (111 loc) · 4.5 KB
/
pythoninstall.py
File metadata and controls
131 lines (111 loc) · 4.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import sys
import os
import platform
import subprocess
import urllib.request
from urllib.error import URLError, HTTPError
import re
# Base HTTP URL for downloads and version listing
BASE_HTTP = 'https://www.python.org/ftp/python'
LISTING_URL = BASE_HTTP + '/'
def fetch_all_versions():
"""Fetch all available Python versions by scraping the FTP directory listing."""
try:
with urllib.request.urlopen(LISTING_URL) as resp:
html = resp.read().decode('utf-8', errors='ignore')
except (URLError, HTTPError) as e:
print(f"Error fetching version listing: {e}")
sys.exit(1)
# Find entries like '3.9.18/'
found = re.findall(r'href=["\'](\d+\.\d+\.\d+)/["\']', html)
versions = sorted(set(found), key=lambda v: list(map(int, v.split('.'))))
return versions
def filter_patches(versions, major):
"""Return all patch versions matching the given major (e.g. '3.9')."""
prefix = major + '.'
return [v for v in versions if v.startswith(prefix)]
def download_file(url, dest):
print(f"Downloading {url}...")
try:
urllib.request.urlretrieve(url, dest)
except Exception as e:
print(f"Download failed: {e}")
sys.exit(1)
print(f"Saved to {dest}")
return dest
def install_on_windows(installer_path):
print("Running Windows installer (quiet, all users)...")
try:
subprocess.run([installer_path, '/quiet', 'InstallAllUsers=1', 'PrependPath=1'], check=True)
print("Installation complete.")
except subprocess.CalledProcessError as e:
print(f"Windows installation failed: {e}")
sys.exit(1)
def install_on_linux(source_tar):
print("Installing from source (Linux)...")
work_dir = "/tmp/python_install"
os.makedirs(work_dir, exist_ok=True)
try:
subprocess.run(["tar", "-xf", source_tar, "-C", work_dir], check=True)
src_dir = os.path.join(work_dir, os.listdir(work_dir)[0])
os.chdir(src_dir)
subprocess.run(["./configure", "--enable-optimizations"], check=True)
subprocess.run(["make", "-j$(nproc)"], shell=True, check=True)
subprocess.run(["sudo", "make", "altinstall"], check=True)
print("Linux installation complete.")
except subprocess.CalledProcessError as e:
print(f"Linux installation failed: {e}")
sys.exit(1)
def main():
majors = ['3.13', '3.12', '3.11', '3.10', '3.9', '3.8', '3.7', '3.6', '3.5']
print("Fetching available versions, please wait...")
all_versions = fetch_all_versions()
print("Choose a Python major version to install:")
for idx, ver in enumerate(majors, start=1):
print(f"{idx}. Python {ver}")
choice = input('Enter number: ').strip()
if not choice.isdigit() or not (1 <= int(choice) <= len(majors)):
print("Invalid selection.")
sys.exit(1)
major = majors[int(choice) - 1]
print(f"You chose Python {major}.")
patches = filter_patches(all_versions, major)
if not patches:
print(f"No patch versions found for Python {major}.")
sys.exit(1)
print("1. Install latest patch for this major")
print("2. Choose a specific patch version")
sub = input('Enter option [1-2]: ').strip()
if sub not in ('1', '2'):
print("Invalid option.")
sys.exit(1)
if sub == '1':
target_version = patches[-1]
else:
print("Available patches:")
for idx, p in enumerate(patches, start=1):
print(f"{idx}. {p}")
p_choice = input('Select patch #: ').strip()
if not p_choice.isdigit() or not (1 <= int(p_choice) <= len(patches)):
print("Invalid patch selection.")
sys.exit(1)
target_version = patches[int(p_choice) - 1]
print(f"Preparing to install Python {target_version}...")
system = platform.system()
if system == 'Windows':
filename = f"python-{target_version}-amd64.exe"
url = f"{BASE_HTTP}/{target_version}/{filename}"
dest = os.path.join(os.getcwd(), filename)
download_file(url, dest)
install_on_windows(dest)
elif system == 'Linux':
filename = f"Python-{target_version}.tgz"
url = f"{BASE_HTTP}/{target_version}/{filename}"
dest = os.path.join('/tmp', filename)
download_file(url, dest)
install_on_linux(dest)
else:
print(f"Unsupported OS: {system}")
sys.exit(1)
if __name__ == '__main__':
main()