Update app.py
Browse files
app.py
CHANGED
@@ -27,9 +27,124 @@ async def stream_log(file_path):
|
|
27 |
else:
|
28 |
await asyncio.sleep(0.1)
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
@app.post("/download-dependencies")
|
31 |
-
async def download_dependencies(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
with NamedTemporaryFile(delete=False) as tmp:
|
34 |
tmp.write(requirements_file.file.read())
|
35 |
tmp_path = tmp.name
|
@@ -39,11 +154,11 @@ async def download_dependencies(requirements_file: UploadFile = File(...)):
|
|
39 |
|
40 |
log_file_path = "/tmp/dependencies/download.log"
|
41 |
with open(log_file_path, "w") as log_file:
|
42 |
-
# Download dependencies
|
43 |
result = subprocess.run(
|
44 |
-
["pip", "download", "-r", tmp_path, "-d", "/tmp/dependencies"],
|
45 |
-
|
46 |
-
|
47 |
)
|
48 |
|
49 |
if result.returncode != 0:
|
@@ -72,12 +187,13 @@ async def download_dependencies(requirements_file: UploadFile = File(...)):
|
|
72 |
except Exception as e:
|
73 |
raise HTTPException(status_code=500, detail=str(e))
|
74 |
finally:
|
75 |
-
if os.path.exists(tmp_path):
|
76 |
os.remove(tmp_path)
|
77 |
-
if os.path.exists(log_file_path):
|
78 |
os.remove(log_file_path)
|
79 |
-
if os.path.exists(tar_path):
|
80 |
-
os.remove(tar_path)
|
|
|
81 |
def download_docker_image(image_name, tag='latest', destination='/tmp/docker-images'):
|
82 |
try:
|
83 |
os.makedirs(destination, exist_ok=True)
|
@@ -142,6 +258,9 @@ async def read_root():
|
|
142 |
<label for="requirements_file">Requirements File:</label>
|
143 |
<input type="file" id="requirements_file" name="requirements_file" accept=".txt" required><br><br>
|
144 |
|
|
|
|
|
|
|
145 |
<input type="submit" id="pip-submit-button" value="Download Dependencies">
|
146 |
</form>
|
147 |
<div id="pip-message" style="display: none; margin-top: 10px;"></div>
|
|
|
27 |
else:
|
28 |
await asyncio.sleep(0.1)
|
29 |
|
30 |
+
import os
|
31 |
+
import subprocess
|
32 |
+
import urllib.request
|
33 |
+
from pathlib import Path
|
34 |
+
|
35 |
+
def install_python_version(python_version: str):
|
36 |
+
python_bin = f"/usr/local/bin/python{python_version}"
|
37 |
+
pip_bin = f"/usr/local/bin/pip{python_version}"
|
38 |
+
|
39 |
+
# Check if Python is already installed
|
40 |
+
if os.path.isfile(python_bin):
|
41 |
+
return python_bin, pip_bin
|
42 |
+
|
43 |
+
# Download and install Python if not present
|
44 |
+
try:
|
45 |
+
url = f"https://www.python.org/ftp/python/{python_version}/Python-{python_version}.tgz"
|
46 |
+
tar_path = f"/tmp/Python-{python_version}.tgz"
|
47 |
+
|
48 |
+
# Download Python source tarball
|
49 |
+
urllib.request.urlretrieve(url, tar_path)
|
50 |
+
|
51 |
+
# Extract tarball
|
52 |
+
subprocess.run(["tar", "-xzf", tar_path, "-C", "/tmp"], check=True)
|
53 |
+
|
54 |
+
# Build and install Python
|
55 |
+
python_src_path = f"/tmp/Python-{python_version}"
|
56 |
+
subprocess.run([f"{python_src_path}/configure"], cwd=python_src_path, check=True)
|
57 |
+
subprocess.run(["make", "-j"], cwd=python_src_path, check=True)
|
58 |
+
subprocess.run(["make", "altinstall", f"EXTRA_CFLAGS='-I/usr/local/include'"], cwd=python_src_path, check=True)
|
59 |
+
|
60 |
+
# Clean up
|
61 |
+
os.remove(tar_path)
|
62 |
+
shutil.rmtree(python_src_path)
|
63 |
+
|
64 |
+
# Update alternatives (if necessary)
|
65 |
+
subprocess.run(["update-alternatives", "--install", "/usr/bin/python3", "python3", python_bin, "1"], check=True)
|
66 |
+
subprocess.run(["update-alternatives", "--install", "/usr/bin/pip", "pip", pip_bin, "1"], check=True)
|
67 |
+
|
68 |
+
except Exception as e:
|
69 |
+
raise RuntimeError(f"Error installing Python {python_version}: {str(e)}")
|
70 |
+
|
71 |
+
return python_bin, pip_bin
|
72 |
+
|
73 |
+
# @app.post("/download-dependencies")
|
74 |
+
# async def download_dependencies(requirements_file: UploadFile = File(...)):
|
75 |
+
# try:
|
76 |
+
# with NamedTemporaryFile(delete=False) as tmp:
|
77 |
+
# tmp.write(requirements_file.file.read())
|
78 |
+
# tmp_path = tmp.name
|
79 |
+
|
80 |
+
# # Ensure the directories exist
|
81 |
+
# os.makedirs("/tmp/dependencies", exist_ok=True)
|
82 |
+
|
83 |
+
# log_file_path = "/tmp/dependencies/download.log"
|
84 |
+
# with open(log_file_path, "w") as log_file:
|
85 |
+
# # Download dependencies
|
86 |
+
# result = subprocess.run(
|
87 |
+
# ["pip", "download", "-r", tmp_path, "-d", "/tmp/dependencies"],
|
88 |
+
# # stdout=log_file,
|
89 |
+
# # stderr=log_file
|
90 |
+
# )
|
91 |
+
|
92 |
+
# if result.returncode != 0:
|
93 |
+
# raise HTTPException(status_code=500, detail="Error downloading dependencies. See log file for details.")
|
94 |
+
|
95 |
+
# # Create a tar file
|
96 |
+
# tar_path = "/tmp/dependencies.tar.gz"
|
97 |
+
# with tarfile.open(tar_path, "w:gz") as tar:
|
98 |
+
# for root, _, files in os.walk("/tmp/dependencies"):
|
99 |
+
# for file in files:
|
100 |
+
# file_path = os.path.join(root, file)
|
101 |
+
# tar.add(file_path, arcname=file)
|
102 |
+
# tar.add(log_file_path, arcname="download.log")
|
103 |
+
|
104 |
+
# # Get the file size
|
105 |
+
# file_size = os.path.getsize(tar_path)
|
106 |
+
|
107 |
+
# # Return the tar file
|
108 |
+
# return StreamingResponse(open(tar_path, "rb"), media_type="application/gzip", headers={
|
109 |
+
# "Content-Disposition": f"attachment; filename=dependencies.tar.gz",
|
110 |
+
# "Content-Length": str(file_size)
|
111 |
+
# })
|
112 |
+
|
113 |
+
# except subprocess.CalledProcessError as e:
|
114 |
+
# raise HTTPException(status_code=500, detail=f"Error downloading dependencies: {str(e)}")
|
115 |
+
# except Exception as e:
|
116 |
+
# raise HTTPException(status_code=500, detail=str(e))
|
117 |
+
# finally:
|
118 |
+
# if os.path.exists(tmp_path):
|
119 |
+
# os.remove(tmp_path)
|
120 |
+
# if os.path.exists(log_file_path):
|
121 |
+
# os.remove(log_file_path)
|
122 |
+
# if os.path.exists(tar_path):
|
123 |
+
# os.remove(tar_path)
|
124 |
+
|
125 |
@app.post("/download-dependencies")
|
126 |
+
async def download_dependencies(
|
127 |
+
requirements_file: UploadFile = File(...),
|
128 |
+
python_version: str = Form(None),
|
129 |
+
):
|
130 |
+
tmp_path = None
|
131 |
+
log_file_path = None
|
132 |
+
tar_path = None
|
133 |
+
|
134 |
try:
|
135 |
+
# Use the current Python version if not specified
|
136 |
+
if not python_version:
|
137 |
+
python_version = "3.11" # Adjust to your current version or use `sys.version_info`
|
138 |
+
|
139 |
+
python_bin, pip_bin = install_python_version(python_version)
|
140 |
+
|
141 |
+
# Validate the installed Python and pip
|
142 |
+
if not os.path.isfile(python_bin):
|
143 |
+
raise HTTPException(status_code=400, detail=f"Python {python_version} installation failed.")
|
144 |
+
|
145 |
+
if not os.path.isfile(pip_bin):
|
146 |
+
raise HTTPException(status_code=400, detail=f"pip for Python {python_version} installation failed.")
|
147 |
+
|
148 |
with NamedTemporaryFile(delete=False) as tmp:
|
149 |
tmp.write(requirements_file.file.read())
|
150 |
tmp_path = tmp.name
|
|
|
154 |
|
155 |
log_file_path = "/tmp/dependencies/download.log"
|
156 |
with open(log_file_path, "w") as log_file:
|
157 |
+
# Download dependencies using the specified Python version
|
158 |
result = subprocess.run(
|
159 |
+
[python_bin, "-m", "pip", "download", "-r", tmp_path, "-d", "/tmp/dependencies"],
|
160 |
+
stdout=log_file,
|
161 |
+
stderr=log_file
|
162 |
)
|
163 |
|
164 |
if result.returncode != 0:
|
|
|
187 |
except Exception as e:
|
188 |
raise HTTPException(status_code=500, detail=str(e))
|
189 |
finally:
|
190 |
+
if tmp_path and os.path.exists(tmp_path):
|
191 |
os.remove(tmp_path)
|
192 |
+
if log_file_path and os.path.exists(log_file_path):
|
193 |
os.remove(log_file_path)
|
194 |
+
if tar_path and os.path.exists(tar_path):
|
195 |
+
os.remove(tar_path)
|
196 |
+
|
197 |
def download_docker_image(image_name, tag='latest', destination='/tmp/docker-images'):
|
198 |
try:
|
199 |
os.makedirs(destination, exist_ok=True)
|
|
|
258 |
<label for="requirements_file">Requirements File:</label>
|
259 |
<input type="file" id="requirements_file" name="requirements_file" accept=".txt" required><br><br>
|
260 |
|
261 |
+
<label for="python_version">Python Version</label>
|
262 |
+
<input type="text" id="python_version" name="python_version"><br><br>
|
263 |
+
|
264 |
<input type="submit" id="pip-submit-button" value="Download Dependencies">
|
265 |
</form>
|
266 |
<div id="pip-message" style="display: none; margin-top: 10px;"></div>
|