-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmake_py3_symlink.py
130 lines (110 loc) · 3.2 KB
/
make_py3_symlink.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env python
# encoding: utf-8
__author__ = 'Lex Darlog (DRL)'
"""
Create a symlink: `python3.7libs` -> `python2.7libs` - to make the lib work both in Python 2 and 3 versions of Houdini.
"""
import os as _os
from os import path as _path
import errno as _errno
import ctypes as _ctypes
import sys as _sys
def win_require_admin_elevation():
# https://stackoverflow.com/questions/130763/request-uac-elevation-from-within-a-python-script
if _os.name != 'nt':
return False
try:
return not _ctypes.windll.shell32.IsUserAnAdmin()
except:
return True
def rerun_as_admin():
try:
# Py2
arg_runas = u'runas'
exe = unicode(_sys.executable)
argv = unicode(u' '.join(_sys.argv))
py3 = False
except Exception:
# Py3
arg_runas = 'runas'
exe = _sys.executable
argv = ' '.join(_sys.argv)
py3 = True
_ctypes.windll.shell32.ShellExecuteW(None, arg_runas, exe, argv, None, 1)
def main(symlink_name='python3.7libs', src_dir='python2.7libs'):
print(
"\nCreating a symlink: {} -> {}\n"
"".format(repr(src_dir), repr(symlink_name))
)
dir_path = _path.dirname(_path.realpath(__file__))
_os.chdir(dir_path)
symlink_full_path = _path.join(dir_path, symlink_name)
src_full_path = _path.join(dir_path, src_dir)
if not _path.exists(src_full_path):
raise OSError(_errno.ENOENT, None, src_full_path)
if not _path.isdir(src_full_path):
raise OSError(_errno.ENOTDIR, None, src_full_path)
if _path.exists(symlink_full_path):
if not _path.islink(symlink_full_path):
raise OSError(_errno.EEXIST, None, symlink_full_path)
# It exists but it's a symlink already
print(
"A symlink is already created: {}\n"
"If you continue, it will be removed and recreated (only symlink itself, not files under it)."
"".format(symlink_full_path)
)
user_input = None
while user_input not in {'', 'y', 'Y', 'n', 'N'}:
user_input = input("Recreate [Y] or exit [n]? >")
if user_input in {'n', 'N'}:
print("\nSymlink {} NOT created.".format(repr(symlink_name)))
return
_os.remove(symlink_full_path)
print("Old symlink removed.")
try:
# Py3
_os.symlink(src_dir, symlink_full_path, target_is_directory=True)
except Exception:
# Py2
_os.symlink(src_dir, symlink_full_path)
print("Symlink created:\n{}\n-> {}\n".format(symlink_full_path, src_dir))
def _run():
import traceback as _traceback
if win_require_admin_elevation():
rerun_as_admin()
return
try:
for d in (
# Just in case, let's use a "shotgun" approach.
# Maybe, there is a single folder name for `python3.*libs`,
# but I wasn't able to google it.
'python3.5libs',
'python3.6libs',
'python3.7libs',
'python3.8libs',
'python3.9libs',
'python3.10libs',
'python3.11libs',
'python3.12libs',
'python3.13libs',
'python3.14libs',
'python3.15libs',
):
main(d)
except OSError as e:
error_str = e.strerror
error_str = '[ERROR {}] {}'.format(
e.errno,
error_str if error_str else _os.strerror(e.errno)
)
filename = e.filename
if filename:
error_str = '{}:\n{}'.format(error_str, filename)
print(error_str)
except Exception as e:
print("".join(
_traceback.format_exception(type(e), e, e.__traceback__)
))
input("Press Enter to exit...")
if __name__ == '__main__':
_run()