-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathenvironmentMngr.py
282 lines (259 loc) · 13 KB
/
environmentMngr.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
import os
import subprocess
from progSpec import cdlog, cdErr
from pmgrHandler import getPackageManagerCMD, findPackageManager
def checkToolLinux(toolName):
if subprocess.call(["which", toolName], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0:
return True
else:
return None
def checkToolWindows(toolName):
if subprocess.call(["Where", toolName], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0:
return True
else:
return None
def downloadFile(fileName, downloadURL):
import urllib3
try:
cdlog(1, "Downloading file: " + fileName)
http = urllib3.PoolManager()
r = http.request('GET', downloadURL, preload_content=False)
except:
cdErr("URL not found: " + downloadURL)
else:
with open(fileName, 'wb') as out:
while True:
data = r.read(1028)
if not data:
break
out.write(data)
r.release_conn()
def packageInstall(packageName):
from pmgrHandler import getPackageManagerCMD
pmgrCMD = getPackageManagerCMD(packageName, findPackageManager(),"install")
cdlog(1, "Package Installing: "+packageName)
if subprocess.call(f'{pmgrCMD}'+" > /dev/null 2>&1", shell=True) == 0:
print("Package installed Successfully")
return True
else:
print("Unable to install package. \nPlease install manually : " + packageName)
def checkPackageStatus(packageName):
# pmgr = getPackageManagerCMD(packageName, findPackageManager())
# pmgrPrepend,pmgrInstallFlag,pmgrQueryLocal,pmgrRemoveFlag,pmgrQueryAvail,queryNotInstalled,getLocalVersion,getAvailVersion = setPackageMgrFlags(pmgr, packageName)
cdlog(1, "Checking for installed Package: "+packageName)
pmgrCMD = getPackageManagerCMD(packageName,findPackageManager(),"queryLocalInstall")
checkInstalled = subprocess.Popen(f'{pmgrCMD}', stdout=subprocess.PIPE, shell=True)
if checkInstalled.stdout.read().isdigit():
_packageToCheck = int(checkInstalled.stdout.read())
else:
_packageToCheck = 1
if _packageToCheck == 0:
cdlog(1, "Package Is Currently Installed")
pmgrCMD = getPackageManagerCMD(packageName,findPackageManager(),"queryLocalVer")
_installedVersion = subprocess.Popen(f'{pmgrCMD}', stdout=subprocess.PIPE, shell=True)
installedVersion = str(_installedVersion.stdout.read()).split(" ")[-0].replace('\\n\'','').replace('b\'','')
cdlog(1, "Installed Version: "+installedVersion)
pmgrCMD = getPackageManagerCMD(packageName,findPackageManager(),"queryAvailVer")
_candidateVersion = subprocess.Popen(f'{pmgrCMD}', stdout=subprocess.PIPE, shell=True)
candidateVersion = str(_candidateVersion.stdout.read()).split("-")[-0].replace('\\n\'','').replace('b\'','')
cdlog(1, "Candidate Version: "+candidateVersion)
return True,installedVersion,candidateVersion
else:
cdlog(1, "Package Is NOT Currently Installed")
pmgrCMD = getPackageManagerCMD(packageName,findPackageManager(),"queryAvailVer")
_candidateVersion = subprocess.Popen(f'{pmgrCMD}', stdout=subprocess.PIPE, shell=True)
candidateVersion = str(_candidateVersion.stdout.read()).split("-")[-0].replace('\\n\'','').replace('b\'','')
cdlog(1, "Candidate Version: "+candidateVersion)
return False,"(none)",candidateVersion
def checkAndUpgradeOSPackageVersions(packageName):
cdlog(1, f"Searching for package: {packageName}")
currentlyInstalled,installedVersion,candidateVersion = checkPackageStatus(packageName)
if currentlyInstalled == False:
cdlog(1, f"Candidate Package available: {candidateVersion}")
packageInstall(packageName)
elif currentlyInstalled == True:
cdlog(1, f"Candidate Package available: {candidateVersion}")
# Compare versions and apply updates only if needed
if installedVersion < candidateVersion:
packageInstall(packageName)
else:
cdlog(1, f"Package already Installed: {packageName}")
def downloadFile(fileName, downloadURL):
CheckPipModules({'urllib3':'1.25'})
import urllib3
try:
cdlog(1, "Downloading file: " + fileName)
http = urllib3.PoolManager()
r = http.request('GET', downloadURL, preload_content=False)
except:
cdErr("URL not found: " + downloadURL)
else:
with open(fileName, 'wb') as out:
while True:
data = r.read(1028)
if not data:
break
out.write(data)
r.release_conn()
def DownloadInstallPipModules(pipCMD):
# Start a sub-process to run pip and a communications pipe to capture stdout and errors for display
pipe = subprocess.Popen(pipCMD, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = pipe.communicate()
decodedOut = bytes.decode(err)
if err:
print("\n\n", decodedOut)
def CheckPipModules(requiredMinimumModulesList):
try:
import pkg_resources
except ModuleNotFoundError:
subprocess.Popen("pip3 install -q %s --disable-pip-version-check pkg_resources", stdout=subprocess.PIPE, shell=True)
import pkg_resources
# Check environment first
AddSystemPath()
# Initialize array of modules
modulesList = []
# Iterate through list of modules
for moduleName in requiredMinimumModulesList:
try:
# Check available package versions
# version = importlib_metadata.version(moduleName)
version = pkg_resources.get_distribution(moduleName).version
except:
# Add each module that string matches from requiredMinimumModulesList with the avoilable packages to the modulesList array
# Each string match is a module that is on the required list and also available from distributions
modulesList.append("%s~=%s" % (moduleName, requiredMinimumModulesList[moduleName]))
else:
# If unmatched...
# Initialize a splitting function
version = version.split(".")
# Parse version currently installed
installedModuleVersion = float(".".join(version[:2]))
# Load package name from module list
moduleVersion = requiredMinimumModulesList[moduleName].split(".")
# Parse required package version
requiredModuleVersion = float(".".join(moduleVersion[:2]))
# Compare required to installed
if installedModuleVersion < requiredModuleVersion:
modulesList.append("%s==%s" % (moduleName, requiredMinimumModulesList[moduleName]))
# For any modules required and available
if modulesList:
print("This program must be used with Python Modules")
# Iterate through list of modules and print list
for module in modulesList:
print(" %s" % module)
# Request permissions to install from user
installationPermission = input("Do you want to install? [Y/n] ")
if installationPermission.lower() == 'y' or installationPermission.lower() == 'yes' or installationPermission == '':
# If user accepts, Iterate through modules:
for module in modulesList:
# set the module base name (omitting versions)
moduleBaseName = module[:module.find("==")]
# Parse the module's latest version
latestModule = module.replace('==','~=')
print("\nInstalling package: ", moduleBaseName)
# send module installation to pip via subprocess
pipCMD = 'pip3 install -q %s --disable-pip-version-check' % latestModule
DownloadInstallPipModules(pipCMD)
else:
# If user declines:
print("\n\nERROR: CodeDog must be used with python modules\n")
# Iterate and list required modules
for module in modulesList:
print(" %s" % module)
exit(1)
def installPipPackage():
from sys import platform
toolName = "pip3"
downloadUrl = "https://bootstrap.pypa.io/get-pip.py"
fileName = "get-pip.py"
if platform == "linux" or platform == "linux2" or platform == "linux-gnu":
if not checkToolLinux(toolName):
checkAndUpgradeOSPackageVersions('python3-pip') # Install PIP3
# If package manager fails to install, try using the bootstrap script
if not checkToolLinux(toolName):
downloadFile(fileName, downloadUrl)
os.system('python3 get-pip.py') # Install PIP3
elif platform == "darwin":
if not checkToolLinux(toolName):
downloadFile(fileName, downloadUrl)
os.system('python get-pip.py') # Install PIP3
elif platform == "win32" or platform == "win64":
if not checkToolWindows(toolName):
downloadFile(fileName, downloadUrl)
os.system('py get-pip.py') # Install PIP3
def AddSystemPath():
from sys import platform
# load system PATH environment variable from OS
pathList = os.get_exec_path()
# Detect current script path
codeDogPath = os.path.dirname(os.path.realpath(__file__))
# If current location is found in the system path, return true
if codeDogPath in pathList: return
# TODO: Research how to permanently set the path for Linux, Mac, Windows via python3
# If a linux or gnu-like terminal is detected (cygwin and msys are bash ports for Windows)
if platform == "linux" or platform == "linux2" or platform == "linux-gnu" or platform == "cygwin" or platform == "msys":
# most linux bash environments utilize ~/.bashrc for user-specific environment config
bashfile = os.path.join(os.path.expanduser('~'), '.bashrc')
# reset flag to detect whether CodeDog is already on system PATH
sytemflag = 0
# bashrc string for setting up codedog env
systemPath = 'PATH="$PATH:$HOME/devl/CodeDog"'
# Parse bashfile and match for exsting string
with open(bashfile, 'r') as f:
if systemPath in f.read():
# If match is positive, set systemflag 1 (installed)
sytemflag = 1
# If parse finds no match (systemflag = 0), ask the user if they want to add it
if not sytemflag:
# Ask user to add to system path or not
addPathPermission = input("Do you want to add CodeDog to the System Path? [Y/n] ")
if addPathPermission.lower() == 'y' or addPathPermission.lower() == 'yes' or addPathPermission == '':
# If yes, open and write to system bashrc
with open(bashfile, 'a') as f:
f.write('\n%s\n' %systemPath)
else:
# Offer manual instructions for adding system PATH to user
print("If you wish to add CodeDog to the system path manually, it is:\n ", codeDogPath)
# If platform detected is MacOS
elif platform == "darwin":
# reset flag to detect whether CodeDog is already on system PATH
sytemflag = 0
# macOS shell environments utilize ~/.zshrc for user-specific environment config
zshrcfile = os.path.join(os.path.expanduser('~'), '.zshrc')
systemPath = 'export PATH="$PATH:$HOME/devl/CodeDog"'
with open(zshrcfile, 'a+') as f:
if systemPath in f.read():
sytemflag = 1
if not sytemflag:
addPathPermission = input("Do you want to add CodeDog to the System Path? [Y/n] ")
if addPathPermission.lower() == 'y' or addPathPermission.lower() == 'yes' or addPathPermission == '':
with open(zshrcfile, 'a+') as f:
f.write('\n%s\n' %systemPath)
else:
print("If you wish to add CodeDog to the system path manually, it is:\n ", codeDogPath)
# If platform detected is Windows
elif platform == "win32" or platform == "win64":
import sys
sytemflag = 0
# load library for handling windows registry files
import winreg as reg
# Set up alias for querying windows registry for Environment Variables
key = reg.OpenKey(reg.HKEY_CURRENT_USER, 'Environment', 0, reg.KEY_ALL_ACCESS)
# Query keys for the system's PATH
try:
value, _ = reg.QueryValueEx(key, 'PATH')
except WindowsError:
value = ''
# If CodeDog is detected in the path, set systemflag = 1 (installed)
if 'CodeDog' in value:
sytemflag = 1
# If parse finds no match (systemflag = 0), ask the user if they want to CodeDog to the system path
if not sytemflag:
addPathPermission = input("Do you want to add CodeDog to the System Path? [Y/n] ")
if addPathPermission.lower() == 'y' or addPathPermission.lower() == 'yes' or addPathPermission == '':
codeDogPath = os.getcwd()
value += ";" + codeDogPath + "\\CodeDog;"
reg.SetValueEx(key, 'PATH', 0, reg.REG_EXPAND_SZ, value)
reg.CloseKey(key)
else:
print("If you wish to add CodeDog to the system path manually, it is:\n ", codeDogPath)