hython 1.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- autopublish/__init__.py +0 -0
- autopublish/publisher.py +64 -0
- easy-path/__init__.py +0 -0
- easy-path/easy-path1.py +68 -0
- fasthardware/__init__.py +2 -0
- fasthardware/fasthardware.py +78 -0
- hython/__init__.py +2 -0
- hython/hython.py +22 -0
- hython-1.0.1.dist-info/METADATA +106 -0
- hython-1.0.1.dist-info/RECORD +14 -0
- hython-1.0.1.dist-info/WHEEL +5 -0
- hython-1.0.1.dist-info/top_level.txt +5 -0
- package_guardian/__init__.py +0 -0
- package_guardian/guardian1.py +69 -0
autopublish/__init__.py
ADDED
|
File without changes
|
autopublish/publisher.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
import sys
|
|
4
|
+
import glob
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def deploy():
|
|
8
|
+
"""
|
|
9
|
+
Automatically builds setup.py and deploys the package to PyPI using token authentication.
|
|
10
|
+
"""
|
|
11
|
+
print("\n๐ [PyPI Auto-Publisher] Starting global deployment pipeline...")
|
|
12
|
+
|
|
13
|
+
# 1. Check for setup.py
|
|
14
|
+
if not os.path.exists("setup.py"):
|
|
15
|
+
print("โ ERROR: 'setup.py' not found in the current directory.")
|
|
16
|
+
print("๐ก Action: Please navigate to the root directory of your project.")
|
|
17
|
+
return
|
|
18
|
+
|
|
19
|
+
# 2. Retrieve PyPI Token from Environment Variables
|
|
20
|
+
pypi_token = os.environ.get("PYPI_TOKEN")
|
|
21
|
+
if not pypi_token:
|
|
22
|
+
print("โ ERROR: Environment variable 'PYPI_TOKEN' is missing.")
|
|
23
|
+
print("๐ก Action: Set your token in the terminal first:")
|
|
24
|
+
print(" Windows (PowerShell): $env:PYPI_TOKEN='pypi-your-token-here'")
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
# 3. Clean up previous build artifacts
|
|
29
|
+
print("\n๐งน [1/3] Cleaning up old build artifacts (dist/build)...")
|
|
30
|
+
if os.path.exists("dist"):
|
|
31
|
+
subprocess.run("rmdir /s /q dist" if os.name == "nt" else "rm -rf dist", shell=True)
|
|
32
|
+
if os.path.exists("build"):
|
|
33
|
+
subprocess.run("rmdir /s /q build" if os.name == "nt" else "rm -rf build", shell=True)
|
|
34
|
+
|
|
35
|
+
# 4. Build source distribution and wheel
|
|
36
|
+
print("\n๐ฆ [2/3] Building source distribution and wheel archives...")
|
|
37
|
+
subprocess.run([sys.executable, "setup.py", "sdist", "bdist_wheel"], check=True)
|
|
38
|
+
|
|
39
|
+
# 5. Find actual built files (Fixing Windows dist/* wildcard 400 bug)
|
|
40
|
+
built_files = glob.glob(os.path.join("dist", "*"))
|
|
41
|
+
if not built_files:
|
|
42
|
+
print("โ ERROR: No built files found in 'dist' folder.")
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
print("\n๐ฅ [3/3] Uploading packages to PyPI warehouse via Twine...")
|
|
46
|
+
|
|
47
|
+
# Inject API token into environment for secure non-interactive authentication
|
|
48
|
+
env_copy = os.environ.copy()
|
|
49
|
+
env_copy["TWINE_USERNAME"] = "__token__"
|
|
50
|
+
env_copy["TWINE_PASSWORD"] = pypi_token
|
|
51
|
+
|
|
52
|
+
# Execute twine upload with explicit file list instead of dist/*
|
|
53
|
+
cmd = ["twine", "upload"] + built_files
|
|
54
|
+
subprocess.run(cmd, check=True, env=env_copy, shell=True)
|
|
55
|
+
|
|
56
|
+
print("\n๐ [SUCCESS] Deployment completed successfully!")
|
|
57
|
+
print("๐ Your library has been published to the global Python ecosystem.")
|
|
58
|
+
|
|
59
|
+
except subprocess.CalledProcessError as e:
|
|
60
|
+
print(f"\nโ ERROR: Command execution failed during build/upload process.")
|
|
61
|
+
print(f"Details: {e}")
|
|
62
|
+
except Exception as e:
|
|
63
|
+
print(f"\nโ ERROR: Unexpected system error occurred.")
|
|
64
|
+
print(f"Details: {e}")
|
easy-path/__init__.py
ADDED
|
File without changes
|
easy-path/easy-path1.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
class Path(str):
|
|
6
|
+
"""
|
|
7
|
+
Super-intuitive Path manipulation library for humans.
|
|
8
|
+
Inherits from 'str' so it can be used directly anywhere a string is required.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
@classmethod
|
|
12
|
+
def here(cls):
|
|
13
|
+
"""Returns the absolute directory path of the currently executing script."""
|
|
14
|
+
# Get the caller's file path frame dynamically
|
|
15
|
+
try:
|
|
16
|
+
import inspect
|
|
17
|
+
frame = inspect.stack()[1]
|
|
18
|
+
module = inspect.getmodule(frame[0])
|
|
19
|
+
if module and hasattr(module, '__file__'):
|
|
20
|
+
return cls(os.path.dirname(os.path.abspath(module.__file__)))
|
|
21
|
+
except Exception:
|
|
22
|
+
pass
|
|
23
|
+
return cls(os.getcwd())
|
|
24
|
+
|
|
25
|
+
def __truediv__(self, next_path):
|
|
26
|
+
"""Enables intuitive slash '/' routing syntax (e.g., Path.here() / 'folder' / 'file.txt')"""
|
|
27
|
+
return Path(os.path.join(self, str(next_path)))
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def exists(self):
|
|
31
|
+
"""Returns True if the path exists on the system."""
|
|
32
|
+
return os.path.exists(self)
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def is_file(self):
|
|
36
|
+
"""Returns True if the path points to a file."""
|
|
37
|
+
return os.path.isfile(self)
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def is_dir(self):
|
|
41
|
+
"""Returns True if the path points to a directory."""
|
|
42
|
+
return os.path.isdir(self)
|
|
43
|
+
|
|
44
|
+
def change_ext(self, new_ext):
|
|
45
|
+
"""Changes or adds a file extension easily."""
|
|
46
|
+
base, _ = os.path.splitext(self)
|
|
47
|
+
if not new_ext.startswith('.'):
|
|
48
|
+
new_ext = '.' + new_ext
|
|
49
|
+
return Path(base + new_ext)
|
|
50
|
+
|
|
51
|
+
def make_dir(self):
|
|
52
|
+
"""Creates the directory if it does not exist. (Like mkdir -p)"""
|
|
53
|
+
os.makedirs(self, exist_ok=True)
|
|
54
|
+
return self
|
|
55
|
+
|
|
56
|
+
def read(self, encoding="utf-8"):
|
|
57
|
+
"""Reads file content in a single line."""
|
|
58
|
+
with open(self, "r", encoding=encoding) as f:
|
|
59
|
+
return f.read()
|
|
60
|
+
|
|
61
|
+
def write(self, content, encoding="utf-8"):
|
|
62
|
+
"""Writes content to the file in a single line. Automatically creates parent directories if missing."""
|
|
63
|
+
parent = os.path.dirname(self)
|
|
64
|
+
if parent:
|
|
65
|
+
os.makedirs(parent, exist_ok=True)
|
|
66
|
+
with open(self, "w", encoding=encoding) as f:
|
|
67
|
+
f.write(str(content))
|
|
68
|
+
return self
|
fasthardware/__init__.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import psutil
|
|
4
|
+
import gc
|
|
5
|
+
|
|
6
|
+
_current_process = psutil.Process(os.getpid())
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def speedup(mode="DEFAULT"):
|
|
10
|
+
print(f"\n [FASTHARDWARE V2] Tuning mode: {mode}...")
|
|
11
|
+
|
|
12
|
+
_elevate_priority(_current_process)
|
|
13
|
+
_optimize_runtime()
|
|
14
|
+
_bind_c_libraries()
|
|
15
|
+
|
|
16
|
+
if mode == "ULTIMATE":
|
|
17
|
+
_supercharge_children()
|
|
18
|
+
|
|
19
|
+
print(" [FASTHARDWARE V2] System hardware optimization complete.\n")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _elevate_priority(process):
|
|
23
|
+
try:
|
|
24
|
+
if sys.platform == "win32":
|
|
25
|
+
process.nice(psutil.HIGH_PRIORITY_CLASS)
|
|
26
|
+
else:
|
|
27
|
+
process.nice(-20)
|
|
28
|
+
except Exception:
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _optimize_runtime():
|
|
33
|
+
try:
|
|
34
|
+
gc.disable()
|
|
35
|
+
gc.set_threshold(700, 10, 10)
|
|
36
|
+
except Exception:
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _bind_c_libraries():
|
|
41
|
+
try:
|
|
42
|
+
total_cores = str(os.cpu_count() or 4)
|
|
43
|
+
for flag in ["OMP_NUM_THREADS", "MKL_NUM_THREADS", "OPENBLAS_NUM_THREADS", "NUMEXPR_NUM_THREADS"]:
|
|
44
|
+
os.environ[flag] = total_cores
|
|
45
|
+
except Exception:
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _supercharge_children():
|
|
50
|
+
try:
|
|
51
|
+
children = _current_process.children(recursive=True)
|
|
52
|
+
if not children:
|
|
53
|
+
print(" -> [MP] No child processes detected yet. Buffers ready.")
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
print(f" -> [MP] Detecting {len(children)} child processes. Intercepting...")
|
|
57
|
+
|
|
58
|
+
all_cores = list(range(os.cpu_count() or 4))
|
|
59
|
+
if not all_cores:
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
for i, child in enumerate(children):
|
|
63
|
+
try:
|
|
64
|
+
if child.is_running():
|
|
65
|
+
_elevate_priority(child)
|
|
66
|
+
assigned_core = [all_cores[i % len(all_cores)]]
|
|
67
|
+
child.cpu_affinity(assigned_core)
|
|
68
|
+
print(f" โโ Child [{child.pid}] Supercharged & Bound to Core {assigned_core}")
|
|
69
|
+
except Exception:
|
|
70
|
+
pass
|
|
71
|
+
except Exception:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def manual_sweep():
|
|
76
|
+
gc.enable()
|
|
77
|
+
gc.collect(0)
|
|
78
|
+
gc.disable()
|
hython/__init__.py
ADDED
hython/hython.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from fasthardware import fasthardware
|
|
2
|
+
import numpy as np
|
|
3
|
+
import aiohttp
|
|
4
|
+
import requests
|
|
5
|
+
from functools import wraps
|
|
6
|
+
|
|
7
|
+
def init(mode="DEFAULT"):
|
|
8
|
+
print("\n๐ [HYTHON] Initializing Hyper-Performance Environment...")
|
|
9
|
+
fasthardware.speedup(mode=mode)
|
|
10
|
+
|
|
11
|
+
def boost(mode="DEFAULT"):
|
|
12
|
+
def decorator(func):
|
|
13
|
+
@wraps(func)
|
|
14
|
+
def wrapper(*args, **kwargs):
|
|
15
|
+
fasthardware.speedup(mode=mode)
|
|
16
|
+
try:
|
|
17
|
+
result = func(*args, **kwargs)
|
|
18
|
+
return result
|
|
19
|
+
finally:
|
|
20
|
+
fasthardware.manual_sweep()
|
|
21
|
+
return wrapper
|
|
22
|
+
return decorator
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hython
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: The ultimate high-performance utility framework for Python, powered by fasthardware.
|
|
5
|
+
Author: Choi Woongyo
|
|
6
|
+
Author-email: chldnsry1214@gmail.com
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: fasthardware>=2.0.3
|
|
14
|
+
Requires-Dist: numpy>=1.24.0
|
|
15
|
+
Requires-Dist: requests>=2.31.0
|
|
16
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
17
|
+
Dynamic: author
|
|
18
|
+
Dynamic: author-email
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: requires-dist
|
|
23
|
+
Dynamic: requires-python
|
|
24
|
+
Dynamic: summary
|
|
25
|
+
|
|
26
|
+
Markdown
|
|
27
|
+
<p align="center">
|
|
28
|
+
<img src="logo.png" alt="hython Official Logo" width="400">
|
|
29
|
+
</p>
|
|
30
|
+
|
|
31
|
+
# ๐ hython
|
|
32
|
+
|
|
33
|
+
[](https://pypi.org/project/hython/)
|
|
34
|
+
[](https://opensource.org/licenses/MIT)
|
|
35
|
+
|
|
36
|
+
**The ultimate high-performance utility framework for Python. Supercharge your functions with just a single decorator.**
|
|
37
|
+
|
|
38
|
+
`hython` is a next-generation mega-utility pack designed to eliminate Python's performance bottlenecks. Powered by the legendary `fasthardware` engine, `hython` allows you to inject hardcore OS-level optimization, strict multicore affinity binding, and ultra-fast computing/networking libraries directly into your critical functions using a simple, native decorator.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## โก Key Features
|
|
43
|
+
|
|
44
|
+
* **Built-in `fasthardware` V2 Engine:** Automatically inherits OS priority escalation and multi-process core-binding (`ULTIMATE` mode).
|
|
45
|
+
* **`@hython.boost` Decorator:** Instantly accelerates specific functions on-demand. Boosts hardware efficiency upon entry and clears memory caches immediately upon exit.
|
|
46
|
+
* **All-in-One High-Speed Battery Pack:** Automatically bundles industry-standard core libraries for high-performance computing and asynchronous networking (`NumPy`, `Requests`, `AioHTTP`).
|
|
47
|
+
* **Zero Configuration boilerplate:** No tedious setups or multi-package imports. Just decorate and launch.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## ๐ฆ Installation
|
|
52
|
+
|
|
53
|
+
Install the complete performance ecosystem with a single command:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install hython
|
|
57
|
+
```
|
|
58
|
+
(This will automatically install fasthardware, numpy, requests, and aiohttp in the background.)
|
|
59
|
+
|
|
60
|
+
๐ ๏ธ Quick Start
|
|
61
|
+
1. Function-Level On-Demand Acceleration (Recommended)
|
|
62
|
+
Simply place the @hython.boost() decorator above any heavy CPU-bound or multi-process function.
|
|
63
|
+
|
|
64
|
+
```Python
|
|
65
|
+
import hython
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
# Supercharge this specific function and its child processes recursively
|
|
69
|
+
```Python
|
|
70
|
+
@hython.boost(mode="ULTIMATE")
|
|
71
|
+
def heavy_data_pipeline():
|
|
72
|
+
# 1. OS priority is elevated to maximum instantly
|
|
73
|
+
# 2. Child processes are strictly bound to isolated CPU cores
|
|
74
|
+
print("Processing massive numbers or real-time streaming...")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
# [hython] Automatically provides pre-imported high-speed utilities
|
|
78
|
+
# e.g., hython.np, hython.requests, hython.aiohttp are ready to use
|
|
79
|
+
|
|
80
|
+
# 3. Upon function completion, memory generation-0 cache is swept safely!
|
|
81
|
+
2. Global Environment Initialization
|
|
82
|
+
If you want to apply the hardware booster globally to your entire script from start to finish:
|
|
83
|
+
|
|
84
|
+
```Python
|
|
85
|
+
import hython
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
# Initialize hyper-performance environment for the entire process lifetime
|
|
89
|
+
```Python
|
|
90
|
+
hython.init(mode="ULTIMATE")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
# Your standard scripts go here...
|
|
94
|
+
๐๏ธ Integrated Ecosystem
|
|
95
|
+
By installing hython, you instantly get optimized wrappers for:
|
|
96
|
+
|
|
97
|
+
System Boosting: fasthardware (OS Scheduling Hijacking & Core Affinity)
|
|
98
|
+
|
|
99
|
+
Fast Vectorization: numpy (C-optimized array operations)
|
|
100
|
+
|
|
101
|
+
Hyper Network I/O: requests & aiohttp (Blazing fast synchronous & asynchronous I/O)
|
|
102
|
+
|
|
103
|
+
๐ License
|
|
104
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
105
|
+
|
|
106
|
+
Developed with โก by Choi Woongyo.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
autopublish/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
autopublish/publisher.py,sha256=LoZbOr5_iQ9y8oT9mQWQn-chbvotVWbajnGFaDaBGZg,2738
|
|
3
|
+
easy-path/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
easy-path/easy-path1.py,sha256=jLW_Pm1GDKmqvEaBoRc_Y6c6fwCQC4mV9n8UQLlSGgY,2333
|
|
5
|
+
fasthardware/__init__.py,sha256=Tffov2cixPb84mx9dW8Le3ylvWIOp1ZOMdTNcaDDN3Y,109
|
|
6
|
+
fasthardware/fasthardware.py,sha256=GlTwb846doiRNK0G4PlSXwKD_UuibMJY7RiGNrX1pTQ,2039
|
|
7
|
+
hython/__init__.py,sha256=-kDqGLBcrjQbA2CaJdFmYE0qEyxYMb58cKPy8izHiGY,130
|
|
8
|
+
hython/hython.py,sha256=ms9HtOC1h1EYSsnjTHzMP0SeaEcZWDdCHLqMjCa9rrc,633
|
|
9
|
+
package_guardian/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
package_guardian/guardian1.py,sha256=a2fb6AWFUNm2KCIKrXCCWCQmQ0P_fe8NO8W9lsIDthY,2576
|
|
11
|
+
hython-1.0.1.dist-info/METADATA,sha256=LODRJF4Gm1ManM8GfV2JalscGpc2e6o4PQpAcbkslWk,4058
|
|
12
|
+
hython-1.0.1.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
13
|
+
hython-1.0.1.dist-info/top_level.txt,sha256=ljiZyZ7jrFA_574QCJSwL4pSaQ_b1qu1RYwx4szN840,59
|
|
14
|
+
hython-1.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import importlib.util
|
|
2
|
+
import os
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
import urllib.request
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_package_size(package_name):
|
|
10
|
+
"""
|
|
11
|
+
Fetches the approximate download size of the package from the PyPI JSON API.
|
|
12
|
+
Returns size in MB as a string, or 'Unknown' if failed.
|
|
13
|
+
"""
|
|
14
|
+
try:
|
|
15
|
+
# Querying PyPI official JSON API
|
|
16
|
+
url = f"https://pypi.org/pypi/{package_name}/json"
|
|
17
|
+
with urllib.request.urlopen(url, timeout=3) as response:
|
|
18
|
+
data = json.loads(response.read().decode())
|
|
19
|
+
|
|
20
|
+
# Look at the latest release files to calculate size
|
|
21
|
+
latest_version = data["info"]["version"]
|
|
22
|
+
releases = data["releases"].get(latest_version, [])
|
|
23
|
+
|
|
24
|
+
if not releases:
|
|
25
|
+
return "Unknown"
|
|
26
|
+
|
|
27
|
+
# Sum up sizes of available wheels/tarballs
|
|
28
|
+
total_bytes = sum(file_info["size"] for file_info in releases if "size" in file_info)
|
|
29
|
+
size_mb = total_bytes / (1024 * 1024)
|
|
30
|
+
return f"{size_mb:.2f} MB"
|
|
31
|
+
except Exception:
|
|
32
|
+
return "Unknown"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def auto_require(package_name, pip_name=None):
|
|
36
|
+
"""
|
|
37
|
+
Checks if a package is installed. If not, prompts the user with size info and installs it.
|
|
38
|
+
"""
|
|
39
|
+
if pip_name is None:
|
|
40
|
+
pip_name = package_name
|
|
41
|
+
|
|
42
|
+
# Check if package is already installed
|
|
43
|
+
spec = importlib.util.find_spec(package_name)
|
|
44
|
+
if spec is not None:
|
|
45
|
+
return # Already installed, pass smoothly
|
|
46
|
+
|
|
47
|
+
print(f"\n๐ [Package Guardian] Missing required package: '{pip_name}'")
|
|
48
|
+
print("โณ Fetching package metadata from PyPI...")
|
|
49
|
+
|
|
50
|
+
# Get download size
|
|
51
|
+
size = get_package_size(pip_name)
|
|
52
|
+
print(f"๐ฆ Package: {pip_name} | Estimated Download Size: {size}")
|
|
53
|
+
|
|
54
|
+
# Prompt user for installation
|
|
55
|
+
response = input(f"โ Would you like to install '{pip_name}' now? (y/n): ").strip().lower()
|
|
56
|
+
|
|
57
|
+
if response in ['y', 'yes']:
|
|
58
|
+
print(f"โก Installing '{pip_name}' via pip... Please wait.")
|
|
59
|
+
try:
|
|
60
|
+
# Execute pip install programmatically
|
|
61
|
+
subprocess.check_call([sys.executable, "-m", "pip", "install", pip_name])
|
|
62
|
+
print(f"๐ [SUCCESS] '{pip_name}' has been successfully installed!\n")
|
|
63
|
+
except subprocess.CalledProcessError as e:
|
|
64
|
+
print(f"โ [ERROR] Failed to install '{pip_name}'.")
|
|
65
|
+
print(f"Details: {e}")
|
|
66
|
+
sys.exit(1)
|
|
67
|
+
else:
|
|
68
|
+
print(f"๐ [CANCELLED] Installation aborted by user. Execution cannot continue without '{pip_name}'.")
|
|
69
|
+
sys.exit(1)
|