forked from multiversx/mx-sdk-py-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
erdpy-up.py
283 lines (215 loc) · 8.67 KB
/
erdpy-up.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
import logging
import os
import os.path
import pathlib
import shutil
import subprocess
import sys
import json
from argparse import ArgumentParser
from typing import Tuple
logger = logging.getLogger("installer")
MIN_REQUIRED_PYTHON_VERSION = (3, 8, 0)
elrondsdk_path = None
exact_version = None
from_branch = None
def main():
global elrondsdk_path
global exact_version
global from_branch
parser = ArgumentParser()
parser.add_argument("--modify-path", dest="modify_path", action="store_true", help="whether to modify $PATH (in profile file)")
parser.add_argument("--no-modify-path", dest="modify_path", action="store_false", help="whether to modify $PATH (in profile file)")
parser.add_argument("--elrondsdk-path", default=get_elrond_sdk_path_default(), help="where to install elrond-sdk")
parser.add_argument("--exact-version", help="the exact version of erdpy to install")
parser.add_argument("--from-branch", help="use a branch of ElrondNetwork/elrond-sdk-erdpy")
parser.set_defaults(modify_path=True)
args = parser.parse_args()
elrondsdk_path = os.path.expanduser(args.elrondsdk_path)
modify_path = args.modify_path
exact_version = args.exact_version
from_branch = args.from_branch
logging.basicConfig(level=logging.DEBUG)
operating_system = get_operating_system()
python_version = (sys.version_info.major, sys.version_info.minor, sys.version_info.micro)
logger.info("Checking user.")
if os.getuid() == 0:
raise InstallError("You should not install erdpy as root.")
logger.info("Checking Python version.")
logger.info(f"Python version: {format_version(python_version)}")
if python_version < MIN_REQUIRED_PYTHON_VERSION:
raise InstallError(f"You need Python {format_version(MIN_REQUIRED_PYTHON_VERSION)} or later.")
logger.info("Checking operating system.")
logger.info(f"Operating system: {operating_system}")
if operating_system != "linux" and operating_system != "osx":
raise InstallError("Your operating system is not supported yet.")
remove_installation()
create_venv()
install_erdpy()
if modify_path:
add_sdk_to_path()
logger.info("""
###############################################################################
Upon restarting the user session, [$ erdpy] command should be available in your shell.
Furthermore, after restarting the user session, you can use [$ source erdpy-activate] to activate the Python virtual environment containing erdpy.
###############################################################################
""")
def format_version(version: Tuple[int, int, int]) -> str:
major, minor, patch = version
return f"{major}.{minor}.{patch}"
def get_operating_system():
aliases = {
"linux": "linux",
"linux1": "linux",
"linux2": "linux",
"darwin": "osx",
"win32": "windows",
"cygwin": "windows",
"msys": "windows"
}
operating_system = aliases.get(sys.platform)
if operating_system is None:
raise InstallError(f"Unknown platform: {sys.platform}")
return operating_system
def remove_installation():
old_folder = os.path.expanduser("~/ElrondSCTools")
if os.path.isdir(old_folder):
answer = input(f"Older installation in {old_folder} has to be removed. Allow? (y/n)")
if answer.lower() not in ["y", "yes"]:
raise InstallError("Installation will not continue.")
shutil.rmtree(old_folder)
logger.info("Removed previous installation (ElrondSCTools).")
folder = get_erdpy_path()
if os.path.isdir(folder):
shutil.rmtree(folder)
logger.info("Removed previous installation (virtual environment).")
def create_venv():
require_venv()
folder = get_erdpy_path()
ensure_folder(folder)
logger.info(f"Creating virtual environment in: {folder}.")
import venv
builder = venv.EnvBuilder(with_pip=True)
builder.clear_directory(folder)
builder.create(folder)
# Create symlink to "bin/activate"
link_path = os.path.join(elrondsdk_path, "erdpy-activate")
if os.path.exists(link_path):
os.remove(link_path)
os.symlink(os.path.join(folder, "bin", "activate"), link_path)
logger.info(f"Virtual environment has been created in: {folder}.")
def require_venv():
operating_system = get_operating_system()
try:
import ensurepip
import venv
logger.info(f"Packages found: {ensurepip}, {venv}.")
except ModuleNotFoundError:
if operating_system == "linux":
python_venv = f"python{sys.version_info.major}.{sys.version_info.minor}-venv"
raise InstallError(f'Packages [venv] or [ensurepip] not found. Please run "sudo apt install {python_venv}" and then run erdpy-up again.')
else:
raise InstallError("Packages [venv] or [ensurepip] not found, please install them first. See https://docs.python.org/3/tutorial/venv.html.")
def get_erdpy_path():
return os.path.join(elrondsdk_path, "erdpy-venv")
def get_elrond_sdk_path_default():
return os.path.expanduser("~/elrondsdk")
def ensure_folder(folder):
pathlib.Path(folder).mkdir(parents=True, exist_ok=True)
def install_erdpy():
logger.info("Installing erdpy in virtual environment...")
if from_branch:
erdpy_to_install = f"https://github.com/ElrondNetwork/elrond-sdk-erdpy/archive/refs/heads/{from_branch}.zip"
else:
erdpy_to_install = "erdpy" if not exact_version else f"erdpy=={exact_version}"
return_code = run_in_venv(["python3", "-m", "pip", "install", "--upgrade", "pip"])
if return_code != 0:
raise InstallError("Could not upgrade pip.")
return_code = run_in_venv(["pip3", "install", "--no-cache-dir", erdpy_to_install])
if return_code != 0:
raise InstallError("Could not install erdpy.")
return_code = run_in_venv(["erdpy", "--version"])
if return_code != 0:
raise InstallError("Could not install erdpy.")
logger.info("Checking and upgrading configuration file")
upgrade_erdpy_config()
# Create symlink to "bin/erdpy"
link_path = os.path.join(elrondsdk_path, "erdpy")
if os.path.exists(link_path):
os.remove(link_path)
os.symlink(os.path.join(get_erdpy_path(), "bin", "erdpy"), link_path)
logger.info("You have successfully installed erdpy.")
def run_in_venv(args):
if "PYTHONHOME" in os.environ:
del os.environ["PYTHONHOME"]
process = subprocess.Popen(args, env={
"PATH": os.path.join(get_erdpy_path(), "bin") + ":" + os.environ["PATH"],
"VIRTUAL_ENV": get_erdpy_path()
})
return process.wait()
def add_sdk_to_path():
logger.info("Checking PATH variable.")
PATH = os.environ["PATH"]
if elrondsdk_path in PATH:
logger.info(f"elrond-sdk path ({elrondsdk_path}) already in $PATH variable.")
return
profile_file = get_profile_file()
logger.info(f"Adding elrond-sdk path [{elrondsdk_path}] to $PATH variable.")
logger.info(f"[{profile_file}] will be modified.")
with open(profile_file, "a") as file:
file.write(f'\nexport PATH="{elrondsdk_path}:$PATH"\t# elrond-sdk\n')
logger.info(f"""
###############################################################################
[{profile_file}] has been modified.
Please RESTART THE USER SESSION.
###############################################################################
""")
def get_profile_file():
operating_system = get_operating_system()
file = None
if operating_system == "linux":
file = "~/.profile"
else:
value = input("""Please choose your preferred shell:
1) zsh
2) bash
""")
if value not in ["1", "2"]:
raise InstallError("Invalid choice.")
value = int(value)
if value == 1:
file = "~/.zshrc"
else:
file = "~/.bash_profile"
return os.path.expanduser(file)
def upgrade_erdpy_config():
config_path = os.path.expanduser("~/elrondsdk/erdpy.json")
if not os.path.exists(config_path):
return
with open(config_path) as f:
data = json.load(f)
if "active" in data:
return
new_data = {
"active": "default",
"configurations": {
"default": data
}
}
with open(config_path, "w") as f:
json.dump(new_data, f, indent=4)
class InstallError(Exception):
inner = None
def __init__(self, message, inner=None):
super().__init__(message)
self.inner = inner
if __name__ == "__main__":
try:
main()
except Exception as err:
logger.fatal(err)
sys.exit(1)
logger.info("""
For more information go to https://docs.elrond.com.
For support, please contact us at https://t.me/ElrondDevelopers.
""")