-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmonkey_patch.py
107 lines (90 loc) · 4.65 KB
/
monkey_patch.py
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
"""
این اسکریپت برای پچ کردن ماژول distutils در محیطهای بدون این ماژول (مانند Python 3.12) استفاده میشود.
این اسکریپت باید قبل از هر import دیگری اجرا شود یا به عنوان ماژول در ابتدای برنامه import شود.
"""
import sys
import logging
from types import ModuleType
from importlib import import_module
# تنظیم لاگینگ
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def monkey_patch_distutils():
"""
اضافه کردن یک ماژول distutils مجازی به sys.modules برای جلوگیری از خطای ImportError.
این روش مخصوصاً برای patcher.py در undetected-chromedriver مفید است.
"""
# همیشه ماژولها را بازنویسی کنیم (حتی اگر قبلاً بارگذاری شده باشند)
if "distutils" in sys.modules:
# حذف ماژول قبلی
del sys.modules["distutils"]
if "distutils.version" in sys.modules:
del sys.modules["distutils.version"]
logger.info("ماژولهای distutils قبلی حذف شدند و بازسازی میشوند.")
logger.info("در حال پچ کردن ماژول distutils...")
# سعی در نصب و import کردن packaging
try:
# ابتدا مطمئن شویم که packaging نصب شده است
import packaging.version
logger.info("ماژول packaging با موفقیت import شد.")
except ImportError:
logger.warning("ماژول packaging نصب نشده است. در حال نصب...")
try:
import subprocess
subprocess.check_call([sys.executable, "-m", "pip", "install", "packaging"])
import packaging.version
logger.info("ماژول packaging با موفقیت نصب و import شد.")
except Exception as e:
logger.error(f"خطا در نصب packaging: {e}")
return False
# ایجاد ماژولهای مجازی
try:
# ایجاد ماژول distutils
distutils_module = ModuleType("distutils")
sys.modules["distutils"] = distutils_module
# ایجاد زیرماژول distutils.version
version_module = ModuleType("distutils.version")
sys.modules["distutils.version"] = version_module
distutils_module.version = version_module
# تعریف LooseVersion با استفاده از packaging.version.parse
from packaging.version import parse
class LooseVersion:
"""
پیادهسازی مجازی LooseVersion با استفاده از packaging.version.parse
این کلاس API مشابه distutils.version.LooseVersion را شبیهسازی میکند.
"""
def __init__(self, vstring):
self.vstring = vstring
self._parse = parse(vstring)
self.version = self._get_version_tuple()
def _get_version_tuple(self):
"""تبدیل نسخه به tuple برای برطرف کردن مشکل version"""
try:
# تلاش برای استخراج اجزای نسخه
version_parts = self.vstring.split('.')
# تبدیل اجزا به عدد در صورت امکان
version_parts = [int(part) if part.isdigit() else part for part in version_parts]
return version_parts
except:
return [0] # مقدار پیشفرض در صورت خطا
def __str__(self):
return self.vstring
def __repr__(self):
return f"LooseVersion('{self.vstring}')"
# اضافه کردن LooseVersion به ماژول version
version_module.LooseVersion = LooseVersion
logger.info("ماژولهای مجازی distutils و distutils.version با موفقیت ایجاد شدند.")
return True
except Exception as e:
logger.error(f"خطا در پچ کردن distutils: {e}")
return False
# اجرای پچ در زمان import شدن ماژول
monkey_patch_distutils()
# برای اجرای مستقیم
if __name__ == "__main__":
success = monkey_patch_distutils()
if success:
print("پچ distutils با موفقیت اجرا شد!")
else:
print("پچ distutils با خطا مواجه شد.")