atomicshop 3.3.3__py3-none-any.whl → 3.3.5__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.
Potentially problematic release.
This version of atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/wrappers/githubw.py +134 -35
- atomicshop/wrappers/socketw/sni.py +1 -1
- {atomicshop-3.3.3.dist-info → atomicshop-3.3.5.dist-info}/METADATA +2 -1
- {atomicshop-3.3.3.dist-info → atomicshop-3.3.5.dist-info}/RECORD +9 -15
- atomicshop/a_installs/ubuntu/nodejs.py +0 -12
- atomicshop/a_installs/win/nodejs.py +0 -11
- atomicshop/wrappers/msiw.py +0 -148
- atomicshop/wrappers/nodejsw/__init__.py +0 -0
- atomicshop/wrappers/nodejsw/install_nodejs_ubuntu.py +0 -183
- atomicshop/wrappers/nodejsw/install_nodejs_windows.py +0 -180
- {atomicshop-3.3.3.dist-info → atomicshop-3.3.5.dist-info}/WHEEL +0 -0
- {atomicshop-3.3.3.dist-info → atomicshop-3.3.5.dist-info}/entry_points.txt +0 -0
- {atomicshop-3.3.3.dist-info → atomicshop-3.3.5.dist-info}/licenses/LICENSE.txt +0 -0
- {atomicshop-3.3.3.dist-info → atomicshop-3.3.5.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
atomicshop/wrappers/githubw.py
CHANGED
|
@@ -78,7 +78,7 @@ class GitHubWrapper:
|
|
|
78
78
|
Usage to download the latest release where the file name is 'test_file.zip':
|
|
79
79
|
git_wrapper = GitHubWrapper(user_name='user_name', repo_name='repo_name')
|
|
80
80
|
git_wrapper.download_and_extract_latest_release(
|
|
81
|
-
target_directory='target_directory',
|
|
81
|
+
target_directory='target_directory', asset_pattern='test_*.zip')
|
|
82
82
|
================================================================================================================
|
|
83
83
|
Usage to get the latest release json:
|
|
84
84
|
git_wrapper = GitHubWrapper(user_name='user_name', repo_name='repo_name')
|
|
@@ -116,6 +116,10 @@ class GitHubWrapper:
|
|
|
116
116
|
self.commits_url: str = str()
|
|
117
117
|
self.contents_url: str = str()
|
|
118
118
|
|
|
119
|
+
self.releases_url: str = str()
|
|
120
|
+
self.releases_per_page: int = 100
|
|
121
|
+
self.releases_starting_page: int = 1
|
|
122
|
+
|
|
119
123
|
if self.user_name and self.repo_name and not self.repo_url:
|
|
120
124
|
self.build_links_from_user_and_repo()
|
|
121
125
|
|
|
@@ -143,6 +147,7 @@ class GitHubWrapper:
|
|
|
143
147
|
self.api_url = f'https://api.{self.domain}/repos/{self.user_name}/{self.repo_name}'
|
|
144
148
|
|
|
145
149
|
self.latest_release_json_url: str = f'{self.api_url}/releases/latest'
|
|
150
|
+
self.releases_url: str = f'{self.api_url}/releases'
|
|
146
151
|
self.commits_url: str = f'{self.api_url}/commits'
|
|
147
152
|
self.contents_url: str = f'{self.api_url}/contents'
|
|
148
153
|
self.branch_download_link = f'{self.api_url}/{self.branch_type_directory}/{self.branch}'
|
|
@@ -272,21 +277,133 @@ class GitHubWrapper:
|
|
|
272
277
|
|
|
273
278
|
download_directory(self.path, current_target_directory, headers)
|
|
274
279
|
|
|
280
|
+
def get_releases_json(
|
|
281
|
+
self,
|
|
282
|
+
asset_pattern: str = None,
|
|
283
|
+
latest: bool = False,
|
|
284
|
+
per_page: int = None,
|
|
285
|
+
starting_page: int = None,
|
|
286
|
+
all_assets: bool = False,
|
|
287
|
+
):
|
|
288
|
+
"""
|
|
289
|
+
This function will get the releases json.
|
|
290
|
+
:param asset_pattern: str, the string pattern to search in the asset names of releases. Wildcards can be used.
|
|
291
|
+
If there is a match, the release will be added to the result list.
|
|
292
|
+
:param latest: bool, if True, will get only the latest release.
|
|
293
|
+
If 'asset_pattern' is provided, 'latest' will find the latest release matching the pattern.
|
|
294
|
+
Of course if you want to get it from all releases, you must set 'all_assets' to True.
|
|
295
|
+
:param per_page: int, the number of releases per page. Default is 100.
|
|
296
|
+
:param starting_page: int, the starting page number. Default is 1.
|
|
297
|
+
:param all_assets: bool, if True, will get all releases matching the pattern across all pages
|
|
298
|
+
OR all assets if no pattern is provided.
|
|
299
|
+
:return:
|
|
300
|
+
"""
|
|
301
|
+
|
|
302
|
+
# If 'latest' is True and no 'asset_pattern' is provided, we only need to get 1 release from page 1.
|
|
303
|
+
# No need to get more assets than the first one.
|
|
304
|
+
if latest and not asset_pattern:
|
|
305
|
+
per_page = 1
|
|
306
|
+
starting_page = 1
|
|
307
|
+
all_assets = False
|
|
308
|
+
# In all other cases, get the releases according to the provided parameters or defaults.
|
|
309
|
+
else:
|
|
310
|
+
if not per_page:
|
|
311
|
+
per_page = self.releases_per_page
|
|
312
|
+
|
|
313
|
+
if not starting_page:
|
|
314
|
+
starting_page = self.releases_starting_page
|
|
315
|
+
|
|
316
|
+
headers: dict = self._get_headers()
|
|
317
|
+
|
|
318
|
+
params: dict = {
|
|
319
|
+
'per_page': per_page,
|
|
320
|
+
'page': starting_page
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
all_releases = []
|
|
324
|
+
while True:
|
|
325
|
+
response = requests.get(self.releases_url, headers=headers, params=params)
|
|
326
|
+
releases = response.json()
|
|
327
|
+
# If no releases found on current page, there will be none on the next as well, break the loop.
|
|
328
|
+
if not releases:
|
|
329
|
+
break
|
|
330
|
+
|
|
331
|
+
# If 'asset_pattern' is provided, filter releases to only those that have matching assets.
|
|
332
|
+
if asset_pattern:
|
|
333
|
+
for release in releases:
|
|
334
|
+
assets = release.get('assets', [])
|
|
335
|
+
matching_assets = [asset for asset in assets if fnmatch.fnmatch(asset.get('name', ''), asset_pattern)]
|
|
336
|
+
if matching_assets:
|
|
337
|
+
all_releases.append(release)
|
|
338
|
+
|
|
339
|
+
if latest:
|
|
340
|
+
return all_releases
|
|
341
|
+
else:
|
|
342
|
+
all_releases.extend(releases)
|
|
343
|
+
|
|
344
|
+
if not all_assets:
|
|
345
|
+
break
|
|
346
|
+
|
|
347
|
+
params['page'] += 1
|
|
348
|
+
|
|
349
|
+
return all_releases
|
|
350
|
+
|
|
351
|
+
def get_latest_release_json(
|
|
352
|
+
self,
|
|
353
|
+
asset_pattern: str = None
|
|
354
|
+
) -> dict:
|
|
355
|
+
"""
|
|
356
|
+
This function will get the latest releases json.
|
|
357
|
+
:param asset_pattern: str, the string pattern to search in the asset names of releases. Wildcards can be used.
|
|
358
|
+
If there is a match, the release will be added to the result list.
|
|
359
|
+
:return: dict, the latest release json.
|
|
360
|
+
"""
|
|
361
|
+
|
|
362
|
+
if asset_pattern:
|
|
363
|
+
releases = self.get_releases_json(
|
|
364
|
+
asset_pattern=asset_pattern,
|
|
365
|
+
latest=True,
|
|
366
|
+
all_assets=True
|
|
367
|
+
)
|
|
368
|
+
else:
|
|
369
|
+
releases = self.get_releases_json(latest=True)
|
|
370
|
+
|
|
371
|
+
if not releases:
|
|
372
|
+
return {}
|
|
373
|
+
else:
|
|
374
|
+
return releases[0]
|
|
375
|
+
|
|
376
|
+
def get_latest_release_version(
|
|
377
|
+
self,
|
|
378
|
+
asset_pattern: str = None
|
|
379
|
+
) -> str:
|
|
380
|
+
"""
|
|
381
|
+
This function will get the latest release version number.
|
|
382
|
+
|
|
383
|
+
:param asset_pattern: str, the string pattern to search in the asset names of releases. Wildcards can be used.
|
|
384
|
+
If there is a match, the release will be added to the result list.
|
|
385
|
+
:return: str, the latest release version number.
|
|
386
|
+
"""
|
|
387
|
+
|
|
388
|
+
latest_release_json: dict = self.get_latest_release_json(asset_pattern=asset_pattern)
|
|
389
|
+
latest_release_version: str = latest_release_json['tag_name']
|
|
390
|
+
return latest_release_version
|
|
391
|
+
|
|
275
392
|
def get_latest_release_url(
|
|
276
393
|
self,
|
|
277
|
-
|
|
278
|
-
|
|
394
|
+
asset_pattern: str,
|
|
395
|
+
exclude_pattern: str = None,
|
|
279
396
|
**kwargs):
|
|
280
397
|
"""
|
|
281
398
|
This function will return the latest release url.
|
|
282
|
-
:param
|
|
283
|
-
:param
|
|
399
|
+
:param asset_pattern: str, the string pattern to search in the latest release. Wildcards can be used.
|
|
400
|
+
:param exclude_pattern: str, the string to exclude from the search. No wildcards can be used.
|
|
284
401
|
:param kwargs: dict, the print arguments for the 'print_api' function.
|
|
285
402
|
:return: str, the latest release url.
|
|
286
403
|
"""
|
|
287
404
|
|
|
288
405
|
# Get the 'assets' key of the latest release json.
|
|
289
|
-
github_latest_releases_list = self.
|
|
406
|
+
github_latest_releases_list = self.get_latest_release_json()['assets']
|
|
290
407
|
|
|
291
408
|
# Get only download urls of the latest releases.
|
|
292
409
|
download_urls: list = list()
|
|
@@ -294,13 +411,13 @@ class GitHubWrapper:
|
|
|
294
411
|
download_urls.append(single_dict['browser_download_url'])
|
|
295
412
|
|
|
296
413
|
# Exclude urls against 'exclude_string'.
|
|
297
|
-
if
|
|
414
|
+
if exclude_pattern:
|
|
298
415
|
for download_url in download_urls:
|
|
299
|
-
if
|
|
416
|
+
if exclude_pattern in download_url:
|
|
300
417
|
download_urls.remove(download_url)
|
|
301
418
|
|
|
302
|
-
# Find urls against '
|
|
303
|
-
found_urls: list = fnmatch.filter(download_urls,
|
|
419
|
+
# Find urls against 'asset_pattern'.
|
|
420
|
+
found_urls: list = fnmatch.filter(download_urls, asset_pattern)
|
|
304
421
|
|
|
305
422
|
# If more than 1 url answer the criteria, we can't download it. The user must be more specific in his input
|
|
306
423
|
# strings.
|
|
@@ -317,15 +434,15 @@ class GitHubWrapper:
|
|
|
317
434
|
def download_latest_release(
|
|
318
435
|
self,
|
|
319
436
|
target_directory: str,
|
|
320
|
-
|
|
437
|
+
asset_pattern: str,
|
|
321
438
|
exclude_string: str = None,
|
|
322
439
|
**kwargs):
|
|
323
440
|
"""
|
|
324
441
|
This function will download the latest release from the GitHub repository.
|
|
325
442
|
:param target_directory: str, the target directory to download the file.
|
|
326
|
-
:param
|
|
443
|
+
:param asset_pattern: str, the string pattern to search in the latest release. Wildcards can be used.
|
|
327
444
|
:param exclude_string: str, the string to exclude from the search. No wildcards can be used.
|
|
328
|
-
The 'excluded_string' will be filtered before the '
|
|
445
|
+
The 'excluded_string' will be filtered before the 'asset_pattern' entries.
|
|
329
446
|
:param kwargs: dict, the print arguments for the 'print_api' function.
|
|
330
447
|
:return:
|
|
331
448
|
"""
|
|
@@ -333,7 +450,7 @@ class GitHubWrapper:
|
|
|
333
450
|
headers: dict = self._get_headers()
|
|
334
451
|
|
|
335
452
|
# Get the latest release url.
|
|
336
|
-
found_url = self.get_latest_release_url(
|
|
453
|
+
found_url = self.get_latest_release_url(asset_pattern=asset_pattern, exclude_string=exclude_string, **kwargs)
|
|
337
454
|
|
|
338
455
|
downloaded_file_path = web.download(
|
|
339
456
|
file_url=found_url, target_directory=target_directory, headers=headers, **kwargs)
|
|
@@ -342,7 +459,7 @@ class GitHubWrapper:
|
|
|
342
459
|
def download_and_extract_latest_release(
|
|
343
460
|
self,
|
|
344
461
|
target_directory: str,
|
|
345
|
-
|
|
462
|
+
asset_pattern: str,
|
|
346
463
|
exclude_string: str = None,
|
|
347
464
|
archive_remove_first_directory: bool = False,
|
|
348
465
|
**kwargs):
|
|
@@ -350,7 +467,7 @@ class GitHubWrapper:
|
|
|
350
467
|
This function will download the latest release from the GitHub repository, extract the file and remove the file,
|
|
351
468
|
leaving only the extracted folder.
|
|
352
469
|
:param target_directory: str, the target directory to download and extract the file.
|
|
353
|
-
:param
|
|
470
|
+
:param asset_pattern: str, the string pattern to search in the latest release. Wildcards can be used.
|
|
354
471
|
:param exclude_string: str, the string to exclude from the search. No wildcards can be used.
|
|
355
472
|
:param archive_remove_first_directory: bool, sets if archive extract function will extract the archive
|
|
356
473
|
without first directory in the archive. Check reference in the
|
|
@@ -362,7 +479,7 @@ class GitHubWrapper:
|
|
|
362
479
|
headers: dict = self._get_headers()
|
|
363
480
|
|
|
364
481
|
# Get the latest release url.
|
|
365
|
-
found_url = self.get_latest_release_url(
|
|
482
|
+
found_url = self.get_latest_release_url(asset_pattern=asset_pattern, exclude_string=exclude_string, **kwargs)
|
|
366
483
|
|
|
367
484
|
web.download_and_extract_file(
|
|
368
485
|
file_url=found_url,
|
|
@@ -371,24 +488,6 @@ class GitHubWrapper:
|
|
|
371
488
|
headers=headers,
|
|
372
489
|
**kwargs)
|
|
373
490
|
|
|
374
|
-
def get_the_latest_release_json(self):
|
|
375
|
-
"""
|
|
376
|
-
This function will get the latest releases json.
|
|
377
|
-
:return:
|
|
378
|
-
"""
|
|
379
|
-
|
|
380
|
-
headers: dict = self._get_headers()
|
|
381
|
-
|
|
382
|
-
response = requests.get(self.latest_release_json_url, headers=headers)
|
|
383
|
-
return response.json()
|
|
384
|
-
|
|
385
|
-
def get_the_latest_release_version_number(self):
|
|
386
|
-
"""
|
|
387
|
-
This function will get the latest release version number.
|
|
388
|
-
:return:
|
|
389
|
-
"""
|
|
390
|
-
return self.get_the_latest_release_json()['tag_name']
|
|
391
|
-
|
|
392
491
|
def get_latest_commit(self) -> dict:
|
|
393
492
|
"""
|
|
394
493
|
This function retrieves the latest commit on the specified branch.
|
|
@@ -274,7 +274,7 @@ class SNIHandler:
|
|
|
274
274
|
|
|
275
275
|
# Setting "server_hostname" as a domain.
|
|
276
276
|
self.sni_received_parameters.ssl_socket.server_hostname = self.sni_received_parameters.destination_name
|
|
277
|
-
print_api("SNI Passed: True",
|
|
277
|
+
print_api("SNI Passed: True", **(print_kwargs or {}))
|
|
278
278
|
message = (
|
|
279
279
|
f"SNI Handler: port {self.sni_received_parameters.ssl_socket.getsockname()[1]}: "
|
|
280
280
|
f"Incoming connection for [{self.sni_received_parameters.ssl_socket.server_hostname}]")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: atomicshop
|
|
3
|
-
Version: 3.3.
|
|
3
|
+
Version: 3.3.5
|
|
4
4
|
Summary: Atomic functions and classes to make developer life easier
|
|
5
5
|
Author: Denis Kras
|
|
6
6
|
License-Expression: MIT
|
|
@@ -14,6 +14,7 @@ License-File: LICENSE.txt
|
|
|
14
14
|
Requires-Dist: wheel
|
|
15
15
|
Requires-Dist: beautifulsoup4
|
|
16
16
|
Requires-Dist: cryptography
|
|
17
|
+
Requires-Dist: dkinst
|
|
17
18
|
Requires-Dist: dnslib
|
|
18
19
|
Requires-Dist: dnspython
|
|
19
20
|
Requires-Dist: docker
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=lCOFyywOc7EF6Esxu6aQIR9lx9HA8beRu1ut7lEQ3oU,122
|
|
2
2
|
atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
|
|
3
3
|
atomicshop/_create_pdf_demo.py,sha256=Yi-PGZuMg0RKvQmLqVeLIZYadqEZwUm-4A9JxBl_vYA,3713
|
|
4
4
|
atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
|
|
@@ -54,11 +54,9 @@ atomicshop/a_installs/ubuntu/docker_rootless.py,sha256=9IPNtGZYjfy1_n6ZRt7gWz9KZ
|
|
|
54
54
|
atomicshop/a_installs/ubuntu/docker_sudo.py,sha256=JzayxeyKDtiuT4Icp2L2LyFRbx4wvpyN_bHLfZ-yX5E,281
|
|
55
55
|
atomicshop/a_installs/ubuntu/elastic_search_and_kibana.py,sha256=yRB-l1zBxdiN6av-FwNkhcBlaeu4zrDPjQ0uPGgpK2I,244
|
|
56
56
|
atomicshop/a_installs/ubuntu/mongodb.py,sha256=xuRJS1qqOZ0EZp7of5R3tTjSu6CwBIxYg8-NaM7othE,230
|
|
57
|
-
atomicshop/a_installs/ubuntu/nodejs.py,sha256=Iax55VJpT2HZsdRv-JvxkLg6JPYpJ-M8_r-wI5ES_yQ,222
|
|
58
57
|
atomicshop/a_installs/ubuntu/pycharm.py,sha256=Ld7YQBwPxrjuZcTG1K4kZqjbBdt8aooCVRa15u5FOmE,157
|
|
59
58
|
atomicshop/a_installs/win/fibratus.py,sha256=TU4e9gdZ_zI73C40uueJ59pD3qmN-UFGdX5GFoVf6cM,179
|
|
60
59
|
atomicshop/a_installs/win/mongodb.py,sha256=AqyItXu19aaoe49pppDxtEkXey6PMy0PoT2Y_RmPpPE,179
|
|
61
|
-
atomicshop/a_installs/win/nodejs.py,sha256=U519Dyt4bsQPbEg_PwnZL5tsbfqDr1BbhxwoQFZsSKo,200
|
|
62
60
|
atomicshop/a_installs/win/pycharm.py,sha256=j_RSd7aDOyC3yDd-_GUTMLlQTmDrqtVFG--oUfGLiZk,140
|
|
63
61
|
atomicshop/a_installs/win/robocorp.py,sha256=Ob8X9Czwd-OR3pudFIFft1dcUjDM0Pw0X03yfPaf3yw,3280
|
|
64
62
|
atomicshop/a_installs/win/wsl_ubuntu_lts.py,sha256=dZbPRLNKFeMd6MotjkE6UDY9cOiIaaclIdR1kGYWI50,139
|
|
@@ -197,8 +195,7 @@ atomicshop/wrappers/astw.py,sha256=VkYfkfyc_PJLIOxByT6L7B8uUmKY6-I8XGZl4t_z828,4
|
|
|
197
195
|
atomicshop/wrappers/configparserw.py,sha256=JwDTPjZoSrv44YKwIRcjyUnpN-FjgXVfMqMK_tJuSgU,22800
|
|
198
196
|
atomicshop/wrappers/cryptographyw.py,sha256=QEUpDn8vUvMg3ADz6-4oC2kbDNC_woDlw7C0zU7qFVM,14233
|
|
199
197
|
atomicshop/wrappers/ffmpegw.py,sha256=wcq0ZnAe0yajBOuTKZCCaKI7CDBjkq7FAgdW5IsKcVE,6031
|
|
200
|
-
atomicshop/wrappers/githubw.py,sha256=
|
|
201
|
-
atomicshop/wrappers/msiw.py,sha256=GQLqud72nfex3kvO1bJSruNriCYTYX1_G1gSf1MPkIA,6118
|
|
198
|
+
atomicshop/wrappers/githubw.py,sha256=bds_8fgyFyHXKwty6-SBS3H3Ueta2IMM5UQFpiFmgHQ,27554
|
|
202
199
|
atomicshop/wrappers/netshw.py,sha256=8WE_576XiiHykwFuE-VkCx5CydMpFlztX4frlEteCtI,6350
|
|
203
200
|
atomicshop/wrappers/numpyw.py,sha256=sBV4gSKyr23kXTalqAb1oqttzE_2XxBooCui66jbAqc,1025
|
|
204
201
|
atomicshop/wrappers/olefilew.py,sha256=biD5m58rogifCYmYhJBrAFb9O_Bn_spLek_9HofLeYE,2051
|
|
@@ -277,9 +274,6 @@ atomicshop/wrappers/mongodbw/install_mongodb_ubuntu.py,sha256=2eEOb35T259lhn5koy
|
|
|
277
274
|
atomicshop/wrappers/mongodbw/install_mongodb_win.py,sha256=64EUQYx7VuMC3ndO2x3nSErh5NZ_BsqMwGvPcybfC-Q,8499
|
|
278
275
|
atomicshop/wrappers/mongodbw/mongo_infra.py,sha256=IjEF0jPzQz866MpTm7rnksnyyWQeUT_B2h2DA9ryAio,2034
|
|
279
276
|
atomicshop/wrappers/mongodbw/mongodbw.py,sha256=CHbDfW9CXzXUs3V97DYQpt-dYlt_gB60JhwqG2tVFQY,56049
|
|
280
|
-
atomicshop/wrappers/nodejsw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
281
|
-
atomicshop/wrappers/nodejsw/install_nodejs_ubuntu.py,sha256=wjpJdfAaY92RYl_L9esDIWuBMGeYH35RHJ5BVgMof8Y,6260
|
|
282
|
-
atomicshop/wrappers/nodejsw/install_nodejs_windows.py,sha256=WvXIcEVnKcQYD-KNwhVP094s__1tt0Ir2Y87MABl8Nc,6283
|
|
283
277
|
atomicshop/wrappers/playwrightw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
284
278
|
atomicshop/wrappers/playwrightw/_tryouts.py,sha256=l1BLkFsiIMNlgv7nfZd1XGEvXQkIQkIcg48__9OaC00,4920
|
|
285
279
|
atomicshop/wrappers/playwrightw/base.py,sha256=WeRpx8otdXuKSr-BjY-uCJTze21kbPpfitoOjKQz5-g,9818
|
|
@@ -328,7 +322,7 @@ atomicshop/wrappers/socketw/exception_wrapper.py,sha256=qW_1CKyPgGlsIt7_jusKkMV4
|
|
|
328
322
|
atomicshop/wrappers/socketw/get_process.py,sha256=aJC-_qFUv3NgWCSUzDI72E4z8_-VTZE9NVZ0CwUoNlM,5698
|
|
329
323
|
atomicshop/wrappers/socketw/receiver.py,sha256=9B3MvcDqr4C3x2fsnjG5SQognd1wRqsBgikxZa0wXG8,8243
|
|
330
324
|
atomicshop/wrappers/socketw/sender.py,sha256=aX_K8l_rHjd5AWb8bi5mt8-YTkMYVRDB6DnPqK_XDUE,4754
|
|
331
|
-
atomicshop/wrappers/socketw/sni.py,sha256=
|
|
325
|
+
atomicshop/wrappers/socketw/sni.py,sha256=YlKavbExcPFfHFLYAJ3i3W6QorY7o4mbQp39g-DnDKA,17911
|
|
332
326
|
atomicshop/wrappers/socketw/socket_client.py,sha256=McBd3DeCy787oDGCEMUEP2awWy3vdkPqr9w-aFh2fBM,22502
|
|
333
327
|
atomicshop/wrappers/socketw/socket_server_tester.py,sha256=Qobmh4XV8ZxLUaw-eW4ESKAbeSLecCKn2OWFzMhadk0,6420
|
|
334
328
|
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=u_v0pjMMrgsdtI0iPPddiLe2wXnBoqTgNM9Y3zjGD4U,41013
|
|
@@ -337,9 +331,9 @@ atomicshop/wrappers/socketw/statistics_csv.py,sha256=_gA8bMX6Sw_UCXKi2y9wNAwlqif
|
|
|
337
331
|
atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
338
332
|
atomicshop/wrappers/winregw/winreg_installed_software.py,sha256=Qzmyktvob1qp6Tjk2DjLfAqr_yXV0sgWzdMW_9kwNjY,2345
|
|
339
333
|
atomicshop/wrappers/winregw/winreg_network.py,sha256=ih0BVNwByLvf9F_Lac4EdmDYYJA3PzMvmG0PieDZrsE,9905
|
|
340
|
-
atomicshop-3.3.
|
|
341
|
-
atomicshop-3.3.
|
|
342
|
-
atomicshop-3.3.
|
|
343
|
-
atomicshop-3.3.
|
|
344
|
-
atomicshop-3.3.
|
|
345
|
-
atomicshop-3.3.
|
|
334
|
+
atomicshop-3.3.5.dist-info/licenses/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
335
|
+
atomicshop-3.3.5.dist-info/METADATA,sha256=QAiSikiYm60q_UBleSyptTY9jvGM6s_7fk2yrncVrec,9311
|
|
336
|
+
atomicshop-3.3.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
337
|
+
atomicshop-3.3.5.dist-info/entry_points.txt,sha256=SJEgEP0KoFtfxuGwe5tOzKfXkjR9Dv6YYug33KNYxyY,69
|
|
338
|
+
atomicshop-3.3.5.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
339
|
+
atomicshop-3.3.5.dist-info/RECORD,,
|
atomicshop/wrappers/msiw.py
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import subprocess
|
|
2
|
-
|
|
3
|
-
from ..print_api import print_api
|
|
4
|
-
from ..permissions import permissions
|
|
5
|
-
from ..import get_process_list
|
|
6
|
-
from .psutilw import processes
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
ERROR_CODES = {
|
|
10
|
-
'1603': 'The App is already installed or Insufficient permissions',
|
|
11
|
-
'1619': 'This installation package could not be opened. Verify that the package exists and that you can '
|
|
12
|
-
'install it manually, also check the installation command line switches'
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class MsiInstallationError(Exception):
|
|
17
|
-
pass
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def get_current_msiexec_processes(msi_file_path: str = None) -> dict:
|
|
21
|
-
"""
|
|
22
|
-
Get the current msiexec processes.
|
|
23
|
-
:param msi_file_path: string, OPTIONAL path to the MSI file to check in the command line.
|
|
24
|
-
:return: list of dicts, each key represents a pid and its values are process name and cmdline.
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
current_processes: dict = (
|
|
28
|
-
get_process_list.GetProcessList(get_method='pywin32', connect_on_init=True).get_processes())
|
|
29
|
-
|
|
30
|
-
current_msiexec_dict: dict = {}
|
|
31
|
-
for pid, process_info in current_processes.items():
|
|
32
|
-
if 'msiexec.exe' in process_info['name']:
|
|
33
|
-
if msi_file_path:
|
|
34
|
-
if msi_file_path in process_info['cmdline']:
|
|
35
|
-
current_msiexec_dict[pid] = process_info
|
|
36
|
-
else:
|
|
37
|
-
current_msiexec_dict[pid] = process_info
|
|
38
|
-
|
|
39
|
-
return current_msiexec_dict
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def wait_for_msiexec_processes_to_finish(msi_file_path: str):
|
|
43
|
-
"""
|
|
44
|
-
Wait for the msiexec processes to finish.
|
|
45
|
-
:param msi_file_path: string, path to the MSI file.
|
|
46
|
-
:return:
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
current_msiexec: dict = get_current_msiexec_processes(msi_file_path)
|
|
50
|
-
current_pid = list(current_msiexec.keys())[0]
|
|
51
|
-
|
|
52
|
-
result_code = processes.wait_for_process(current_pid)
|
|
53
|
-
if result_code != 0:
|
|
54
|
-
raise Exception(f"MSI Installation failed. Return code: {result_code}")
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def install_msi(
|
|
58
|
-
msi_path,
|
|
59
|
-
silent_no_gui: bool = False,
|
|
60
|
-
silent_progress_bar: bool = False,
|
|
61
|
-
no_restart: bool = False,
|
|
62
|
-
terminate_required_processes: bool = False,
|
|
63
|
-
additional_args: str = None,
|
|
64
|
-
create_log_near_msi: bool = False,
|
|
65
|
-
log_file_path: str = None,
|
|
66
|
-
scan_log_for_errors: bool = False,
|
|
67
|
-
# as_admin=True,
|
|
68
|
-
print_kwargs: dict = None):
|
|
69
|
-
"""
|
|
70
|
-
Install an MSI file silently.
|
|
71
|
-
:param msi_path: str, path to the MSI file.
|
|
72
|
-
:param silent_no_gui: bool, whether to run the installation silently, without showing GUI.
|
|
73
|
-
:param silent_progress_bar: bool, whether to show a progress bar during silent installation.
|
|
74
|
-
:param no_restart: bool, whether to restart the computer after installation.
|
|
75
|
-
:param terminate_required_processes: bool, whether to terminate processes that are required by the installation.
|
|
76
|
-
:param additional_args: str, additional arguments to pass to the msiexec command.
|
|
77
|
-
:param create_log_near_msi: bool, whether to create a log file near the MSI file.
|
|
78
|
-
If the msi file located in 'c:\\path\\to\\file.msi', the log file will be created in 'c:\\path\\to\\file.log'.
|
|
79
|
-
The log options that will be used: /l*v c:\\path\\to\\file.log
|
|
80
|
-
:param log_file_path: str, path to the log file. Even if 'create_log_near_msi' is False, you can specify a custom
|
|
81
|
-
path for the log file, and it will be created.
|
|
82
|
-
The log options that will be used: /l*v c:\\path\\to\\file.log
|
|
83
|
-
:param scan_log_for_errors: bool, whether to scan the log file for errors in case of failure.
|
|
84
|
-
# :param as_admin: bool, whether to run the installation as administrator.
|
|
85
|
-
:param print_kwargs: dict, print_api kwargs.
|
|
86
|
-
:return:
|
|
87
|
-
"""
|
|
88
|
-
|
|
89
|
-
if not permissions.is_admin():
|
|
90
|
-
raise PermissionError("This function requires administrator privileges.")
|
|
91
|
-
|
|
92
|
-
if silent_progress_bar and silent_no_gui:
|
|
93
|
-
raise ValueError("silent_progress_bar and silent_no_gui cannot be both True.")
|
|
94
|
-
|
|
95
|
-
if create_log_near_msi and log_file_path:
|
|
96
|
-
raise ValueError("create_log_near_msi and log_file_path cannot be both set.")
|
|
97
|
-
|
|
98
|
-
if create_log_near_msi:
|
|
99
|
-
log_file_path = msi_path.replace('.msi', '.log')
|
|
100
|
-
|
|
101
|
-
if scan_log_for_errors and not log_file_path:
|
|
102
|
-
raise ValueError("[scan_log_for_errors] is set, but [log_file_path] or [create_log_near_msi] is not set.")
|
|
103
|
-
|
|
104
|
-
# Define the msiexec command
|
|
105
|
-
command = f'msiexec /i "{msi_path}"'
|
|
106
|
-
|
|
107
|
-
if silent_no_gui:
|
|
108
|
-
command = f"{command} /qn"
|
|
109
|
-
if silent_progress_bar:
|
|
110
|
-
command = f"{command} /qb"
|
|
111
|
-
if no_restart:
|
|
112
|
-
command = f"{command} /norestart"
|
|
113
|
-
|
|
114
|
-
if log_file_path:
|
|
115
|
-
command = f"{command} /l*v {log_file_path}"
|
|
116
|
-
|
|
117
|
-
if terminate_required_processes:
|
|
118
|
-
command = f"{command} REBOOT=ReallySuppress"
|
|
119
|
-
|
|
120
|
-
if additional_args:
|
|
121
|
-
if additional_args.startswith(' '):
|
|
122
|
-
additional_args = additional_args[1:]
|
|
123
|
-
command = f"{command} {additional_args}"
|
|
124
|
-
|
|
125
|
-
# if as_admin:
|
|
126
|
-
# command = win_permissions.get_command_to_run_as_admin_windows(command)
|
|
127
|
-
|
|
128
|
-
# Run the command
|
|
129
|
-
result = subprocess.run(command, capture_output=True, text=True)
|
|
130
|
-
|
|
131
|
-
# Check the result
|
|
132
|
-
if result.returncode == 0:
|
|
133
|
-
print_api("MSI Installation completed.", color="green", **(print_kwargs or {}))
|
|
134
|
-
else:
|
|
135
|
-
message = (f"Installation failed. Return code: {result.returncode}\n{ERROR_CODES.get(str(result.returncode), '')}\n"
|
|
136
|
-
f"MSI path: {msi_path}\nCommand: {command}\nOutput: {result.stdout}\nError: {result.stderr}")
|
|
137
|
-
|
|
138
|
-
if scan_log_for_errors:
|
|
139
|
-
with open(log_file_path, 'r', encoding='utf-16 le') as f:
|
|
140
|
-
log_content = f.read()
|
|
141
|
-
if 'error' in log_content.lower():
|
|
142
|
-
# Get the error text of the lines that contain 'error'.
|
|
143
|
-
error_lines = [line for line in log_content.split('\n') if 'error' in line.lower()]
|
|
144
|
-
for line in error_lines:
|
|
145
|
-
message += f"\n{line}"
|
|
146
|
-
|
|
147
|
-
print_api(message, color="red", **(print_kwargs or {}))
|
|
148
|
-
raise MsiInstallationError("MSI Installation Failed.")
|
|
File without changes
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import subprocess
|
|
2
|
-
import requests
|
|
3
|
-
import argparse
|
|
4
|
-
|
|
5
|
-
from ...basics import booleans
|
|
6
|
-
from .. import githubw, ubuntu_terminal
|
|
7
|
-
from ...print_api import print_api
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def is_nodejs_installed():
|
|
11
|
-
"""
|
|
12
|
-
The function will check if Node.js is installed.
|
|
13
|
-
:return: bool.
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
try:
|
|
17
|
-
# Run the command 'node -v'
|
|
18
|
-
result = subprocess.run(['node', '-v'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
19
|
-
|
|
20
|
-
# Check if the command was successful
|
|
21
|
-
if result.returncode == 0:
|
|
22
|
-
message = f"Node.js installed. Version: {result.stdout.strip()}"
|
|
23
|
-
print_api(message, color='green')
|
|
24
|
-
return True
|
|
25
|
-
else:
|
|
26
|
-
print_api("Node.js is not installed.")
|
|
27
|
-
return False
|
|
28
|
-
except FileNotFoundError:
|
|
29
|
-
print_api("Node command not found. Node.js is not installed.")
|
|
30
|
-
return False
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def get_nodejs_latest_version_number(
|
|
34
|
-
by_github_api: bool = True,
|
|
35
|
-
_by_nodejs_website: bool = False,
|
|
36
|
-
get_major: bool = False
|
|
37
|
-
) -> str:
|
|
38
|
-
"""
|
|
39
|
-
The function will get the latest version number of Node.js.
|
|
40
|
-
:param by_github_api: bool, if True, the function will get the version number using the GitHub API.
|
|
41
|
-
Limitations: rate limits apply.
|
|
42
|
-
:param _by_nodejs_website: bool, if True, the function will get the version number using the Node.js website.
|
|
43
|
-
Limitations: the website structure can change and the json file is relatively large.
|
|
44
|
-
This is only for reference, it is not tested.
|
|
45
|
-
:param get_major: bool, if True, the function will return only the major version number string.
|
|
46
|
-
:return: str.
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
if by_github_api and _by_nodejs_website:
|
|
50
|
-
raise ValueError("Only one of the arguments can be True.")
|
|
51
|
-
elif not by_github_api and not _by_nodejs_website:
|
|
52
|
-
raise ValueError("At least one of the arguments must be True.")
|
|
53
|
-
|
|
54
|
-
latest_version = ''
|
|
55
|
-
if by_github_api:
|
|
56
|
-
github_wrapper = githubw.GitHubWrapper('nodejs', 'node')
|
|
57
|
-
latest_version = github_wrapper.get_the_latest_release_version_number()
|
|
58
|
-
elif _by_nodejs_website:
|
|
59
|
-
url = "https://nodejs.org/dist/index.json"
|
|
60
|
-
response = requests.get(url)
|
|
61
|
-
versions = response.json()
|
|
62
|
-
latest_version = versions[0]['version'] # Assuming the first one is the latest.
|
|
63
|
-
|
|
64
|
-
if get_major:
|
|
65
|
-
latest_version = latest_version.replace('v', '')
|
|
66
|
-
latest_version = latest_version.split('.')[0]
|
|
67
|
-
|
|
68
|
-
return latest_version
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def install_nodejs_ubuntu(
|
|
72
|
-
install_latest_version: bool = False,
|
|
73
|
-
install_lts: bool = True,
|
|
74
|
-
install_by_version_number: str = None,
|
|
75
|
-
force_install: bool = False
|
|
76
|
-
):
|
|
77
|
-
"""
|
|
78
|
-
The function will install Node.js on Ubuntu.
|
|
79
|
-
|
|
80
|
-
:param install_latest_version: bool, if True, the function will install the latest version of Node.js.
|
|
81
|
-
:param install_lts: bool, if True, the function will install the LTS version of Node.js.
|
|
82
|
-
:param install_by_version_number: str, the version number of Node.js to install.
|
|
83
|
-
:param force_install: bool, if True, the function will install Node.js even if it is already installed.
|
|
84
|
-
|
|
85
|
-
:return:
|
|
86
|
-
"""
|
|
87
|
-
|
|
88
|
-
booleans.is_only_1_true_in_list(
|
|
89
|
-
booleans_list_of_tuples=[
|
|
90
|
-
(install_latest_version, 'install_latest_version'),
|
|
91
|
-
(install_lts, 'install_lts'),
|
|
92
|
-
(install_by_version_number, 'install_by_version_number')
|
|
93
|
-
],
|
|
94
|
-
raise_if_all_false=True
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
# Check if Node.js is already installed.
|
|
98
|
-
if is_nodejs_installed():
|
|
99
|
-
if not force_install:
|
|
100
|
-
return
|
|
101
|
-
|
|
102
|
-
# NodeSource is listed as source under official Node.js GitHub repository:
|
|
103
|
-
# https://github.com/nodejs/node?tab=readme-ov-file#current-and-lts-releases
|
|
104
|
-
print_api("Adding NodeSource repository...")
|
|
105
|
-
|
|
106
|
-
# Fetch and execute the NodeSource repository setup script.
|
|
107
|
-
if install_latest_version:
|
|
108
|
-
install_by_version_number: str = get_nodejs_latest_version_number(get_major=True)
|
|
109
|
-
|
|
110
|
-
command: str = ''
|
|
111
|
-
if install_latest_version or install_by_version_number:
|
|
112
|
-
command = f"curl -fsSL https://deb.nodesource.com/setup_{install_by_version_number}.x | sudo -E bash -"
|
|
113
|
-
elif install_lts:
|
|
114
|
-
command = "curl -fsSL https://deb.nodesource.com/setup_current.x | sudo -E bash -"
|
|
115
|
-
|
|
116
|
-
_ = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
|
|
117
|
-
|
|
118
|
-
ubuntu_terminal.update_system_packages()
|
|
119
|
-
ubuntu_terminal.install_packages(['nodejs'])
|
|
120
|
-
|
|
121
|
-
# Check if Node.js is installed.
|
|
122
|
-
is_nodejs_installed()
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def install_nodejs_main():
|
|
126
|
-
"""
|
|
127
|
-
The function will install Node.js on Ubuntu.
|
|
128
|
-
:return:
|
|
129
|
-
"""
|
|
130
|
-
|
|
131
|
-
# Create the parser.
|
|
132
|
-
parser = argparse.ArgumentParser(description="Install Node.js on Ubuntu.")
|
|
133
|
-
parser.add_argument(
|
|
134
|
-
'--latest',
|
|
135
|
-
action='store_true',
|
|
136
|
-
help="Install the latest version of Node.js."
|
|
137
|
-
)
|
|
138
|
-
parser.add_argument(
|
|
139
|
-
'--lts',
|
|
140
|
-
action='store_true',
|
|
141
|
-
help="Install the LTS version of Node.js."
|
|
142
|
-
)
|
|
143
|
-
parser.add_argument(
|
|
144
|
-
'--version',
|
|
145
|
-
type=str,
|
|
146
|
-
help="Install a specific version of Node.js."
|
|
147
|
-
)
|
|
148
|
-
parser.add_argument(
|
|
149
|
-
'--force',
|
|
150
|
-
action='store_true',
|
|
151
|
-
help="Force the installation of Node.js."
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
# Parse the arguments.
|
|
155
|
-
args = parser.parse_args()
|
|
156
|
-
|
|
157
|
-
install_nodejs_ubuntu(
|
|
158
|
-
install_latest_version=args.latest,
|
|
159
|
-
install_lts=args.lts,
|
|
160
|
-
install_by_version_number=args.version,
|
|
161
|
-
force_install=args.force
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
def install_npm_package_ubuntu(package_name: str, sudo: bool = True):
|
|
166
|
-
"""
|
|
167
|
-
The function will install a npm package on Ubuntu.
|
|
168
|
-
:param package_name: str, the name of the package to install.
|
|
169
|
-
:param sudo: bool, if True, the function will use sudo.
|
|
170
|
-
NPM commands require sudo to install global packages.
|
|
171
|
-
:return:
|
|
172
|
-
"""
|
|
173
|
-
|
|
174
|
-
# Check if Node.js is installed.
|
|
175
|
-
if not is_nodejs_installed():
|
|
176
|
-
return
|
|
177
|
-
|
|
178
|
-
command = f"npm install -g {package_name}"
|
|
179
|
-
|
|
180
|
-
if sudo:
|
|
181
|
-
command = f"sudo {command}"
|
|
182
|
-
|
|
183
|
-
_ = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import subprocess
|
|
2
|
-
import os
|
|
3
|
-
import requests
|
|
4
|
-
import time
|
|
5
|
-
import tempfile
|
|
6
|
-
|
|
7
|
-
from ... import web
|
|
8
|
-
from ...permissions import permissions
|
|
9
|
-
from .. import msiw
|
|
10
|
-
from ...print_api import print_api
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
WINDOWS_X64_SUFFIX: str = "x64.msi"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class NodeJSWindowsInstallerNoVersionsFound(Exception):
|
|
17
|
-
pass
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class NodeJSWindowsInstallerMoreThanOneVersionFound(Exception):
|
|
21
|
-
pass
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class NodeJSWindowsInstallerFailedToExtractFileNameFromString(Exception):
|
|
25
|
-
pass
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class NodeJSWindowsInstallerFailedToExtractVersionInString(Exception):
|
|
29
|
-
pass
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def is_nodejs_installed():
|
|
33
|
-
"""
|
|
34
|
-
Check if Node.js is installed by trying to run 'node -v'.
|
|
35
|
-
"""
|
|
36
|
-
print_api("Checking if Node.js is installed...")
|
|
37
|
-
try:
|
|
38
|
-
try:
|
|
39
|
-
node_version = subprocess.check_output(["node", "-v"], text=True)
|
|
40
|
-
except FileNotFoundError:
|
|
41
|
-
print_api(f"node.exe is not found.", color="red")
|
|
42
|
-
raise
|
|
43
|
-
|
|
44
|
-
node_version = node_version.replace("\n", "")
|
|
45
|
-
print_api(f"node.exe is found. Version: {node_version}", color="green")
|
|
46
|
-
|
|
47
|
-
try:
|
|
48
|
-
npm_version = subprocess.check_output(["npm.cmd", "-v"], text=True).strip()
|
|
49
|
-
except FileNotFoundError:
|
|
50
|
-
print_api(f"npm.cmd is not found.", color="red")
|
|
51
|
-
raise
|
|
52
|
-
|
|
53
|
-
npm_version = npm_version.replace("\n", "")
|
|
54
|
-
print_api(f"npm.cmd is found. Version: {npm_version}", color="green")
|
|
55
|
-
print_api("Node.js is installed.")
|
|
56
|
-
return True
|
|
57
|
-
except FileNotFoundError:
|
|
58
|
-
print_api("Node.js is not installed.")
|
|
59
|
-
return False
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def add_nodejs_to_path():
|
|
63
|
-
"""
|
|
64
|
-
Add Node.js to the PATH for the current CMD session.
|
|
65
|
-
"""
|
|
66
|
-
print_api("Adding Node.js to the PATH for the current session...")
|
|
67
|
-
# Get the installation directory from the default Node.js install path
|
|
68
|
-
program_files = os.environ.get("ProgramFiles", "C:\\Program Files")
|
|
69
|
-
nodejs_path = os.path.join(program_files, "nodejs")
|
|
70
|
-
|
|
71
|
-
if os.path.exists(nodejs_path):
|
|
72
|
-
print_api(f"Node.js installation found at: {nodejs_path}")
|
|
73
|
-
current_path = os.environ.get("PATH", "")
|
|
74
|
-
if nodejs_path not in current_path:
|
|
75
|
-
# Add Node.js to the PATH for the current process
|
|
76
|
-
os.environ["PATH"] = f"{nodejs_path};{current_path}"
|
|
77
|
-
print_api("Node.js has been added to the PATH for this session.")
|
|
78
|
-
else:
|
|
79
|
-
print_api("Node.js is already in the PATH.")
|
|
80
|
-
else:
|
|
81
|
-
print_api("Node.js installation directory not found.")
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def get_latest_nodejs_version():
|
|
85
|
-
"""
|
|
86
|
-
Fetch the latest Node.js version from the official Node.js website.
|
|
87
|
-
"""
|
|
88
|
-
print_api("Fetching the latest Node.js version...")
|
|
89
|
-
url = "https://nodejs.org/dist/latest/SHASUMS256.txt"
|
|
90
|
-
|
|
91
|
-
response = requests.get(url, timeout=10)
|
|
92
|
-
response.raise_for_status()
|
|
93
|
-
# Parse the file for the Node.js version
|
|
94
|
-
found_versions: list = []
|
|
95
|
-
for line in response.text.splitlines():
|
|
96
|
-
if line.endswith(WINDOWS_X64_SUFFIX):
|
|
97
|
-
found_versions.append(line)
|
|
98
|
-
|
|
99
|
-
if not found_versions:
|
|
100
|
-
raise NodeJSWindowsInstallerNoVersionsFound("No Node.js versions found in [https://nodejs.org/dist/latest/SHASUMS256.txt]")
|
|
101
|
-
elif len(found_versions) > 1:
|
|
102
|
-
raise NodeJSWindowsInstallerMoreThanOneVersionFound(f"More than one Node.js version found:\n"
|
|
103
|
-
f"{'\n'.join(found_versions)}")
|
|
104
|
-
|
|
105
|
-
try:
|
|
106
|
-
file_name = found_versions[0].split(" ")[-1]
|
|
107
|
-
except IndexError:
|
|
108
|
-
raise NodeJSWindowsInstallerFailedToExtractFileNameFromString("Failed to extract the file name from the string.")
|
|
109
|
-
|
|
110
|
-
try:
|
|
111
|
-
version = file_name.replace("node-v", "").replace(f"-{WINDOWS_X64_SUFFIX}", "")
|
|
112
|
-
except Exception:
|
|
113
|
-
raise NodeJSWindowsInstallerFailedToExtractVersionInString("Failed to extract the version from the string.")
|
|
114
|
-
|
|
115
|
-
print_api(f"Latest Node.js version: {version}")
|
|
116
|
-
return version
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def download_nodejs_installer(version):
|
|
120
|
-
"""
|
|
121
|
-
Download the Node.js MSI installer for Windows.
|
|
122
|
-
"""
|
|
123
|
-
|
|
124
|
-
version = f"v{version}"
|
|
125
|
-
nodejs_base_url = f"https://nodejs.org/dist/{version}/"
|
|
126
|
-
file_name = f"node-{version}-x64.msi"
|
|
127
|
-
download_url = nodejs_base_url + file_name
|
|
128
|
-
print_api(f"Downloading Node.js installer from: {download_url}")
|
|
129
|
-
|
|
130
|
-
# Make temporary directory to store the installer
|
|
131
|
-
temp_dir = tempfile.gettempdir()
|
|
132
|
-
temp_file_path = web.download(download_url, temp_dir)
|
|
133
|
-
return temp_file_path
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
def clean_up(installer_path):
|
|
137
|
-
"""
|
|
138
|
-
Remove the installer file after installation.
|
|
139
|
-
"""
|
|
140
|
-
try:
|
|
141
|
-
if os.path.exists(installer_path):
|
|
142
|
-
os.remove(installer_path)
|
|
143
|
-
print_api(f"Removed installer: {installer_path}")
|
|
144
|
-
except Exception as e:
|
|
145
|
-
print_api(f"Failed to clean up the installer: {e}")
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
def install_nodejs_windows() -> int:
|
|
149
|
-
"""
|
|
150
|
-
Install Node.js on Windows.
|
|
151
|
-
If you're installing as part of a cmd script that continues and installs npm packages, you can do something like this:
|
|
152
|
-
if not install_nodejs_windows.is_nodejs_installed():
|
|
153
|
-
install_nodejs_windows.is_nodejs_installed()
|
|
154
|
-
install_nodejs_windows.install_nodejs_windows()
|
|
155
|
-
install_nodejs_windows.add_nodejs_to_path()
|
|
156
|
-
if not install_nodejs_windows.is_nodejs_installed():
|
|
157
|
-
print_api("Node.js installation failed.")
|
|
158
|
-
return 1
|
|
159
|
-
:return:
|
|
160
|
-
"""
|
|
161
|
-
if not permissions.is_admin():
|
|
162
|
-
print_api("This script requires administrative privileges to install Node.js.")
|
|
163
|
-
return 1
|
|
164
|
-
|
|
165
|
-
print_api("Starting Node.js installation process...")
|
|
166
|
-
version = get_latest_nodejs_version()
|
|
167
|
-
if not version:
|
|
168
|
-
print_api("Exiting: Could not fetch the latest Node.js version.")
|
|
169
|
-
return 1
|
|
170
|
-
|
|
171
|
-
installer_path = download_nodejs_installer(version)
|
|
172
|
-
if not installer_path:
|
|
173
|
-
print_api("Exiting: Failed to download the Node.js installer.")
|
|
174
|
-
return 1
|
|
175
|
-
|
|
176
|
-
msiw.install_msi(installer_path, silent_progress_bar=True)
|
|
177
|
-
time.sleep(5) # Wait a few seconds for the installation to complete
|
|
178
|
-
clean_up(installer_path)
|
|
179
|
-
print_api("Installation process finished.")
|
|
180
|
-
return 0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|