atomicshop 2.19.11__py3-none-any.whl → 2.19.12__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 CHANGED
@@ -1,4 +1,4 @@
1
1
  """Atomic Basic functions and classes to make developer life easier"""
2
2
 
3
3
  __author__ = "Den Kras"
4
- __version__ = '2.19.11'
4
+ __version__ = '2.19.12'
@@ -1,11 +1,12 @@
1
- # v1.0.2 - 26.03.2023 20:40
2
1
  import sys
3
2
 
4
3
 
5
- def query_positive_negative(question_string: str,
6
- add_first_values_to_question: bool = True,
7
- positive_answers: list = None,
8
- negative_answers: list = None) -> bool:
4
+ def query_positive_negative(
5
+ question_string: str,
6
+ add_first_values_to_question: bool = True,
7
+ positive_answers: list = None,
8
+ negative_answers: list = None
9
+ ) -> bool:
9
10
  """
10
11
  Ask for "yes" / "no" input to a question that is passed as a "question_string".
11
12
  Returns 'True' for 'positive' answers and 'False' for 'negative' answers.
@@ -31,10 +32,8 @@ def query_positive_negative(question_string: str,
31
32
  if add_first_values_to_question:
32
33
  question_string = f'{question_string} [{positive_answers[0]}/{negative_answers[0]}]'
33
34
 
34
- # Defining variable as False for While loop to run
35
- right_answer = False
36
35
  # As long as "right_answer" is False the loop will execute again
37
- while not right_answer:
36
+ while True:
38
37
  # Print the passed question
39
38
  print(question_string)
40
39
  # Get the input from the console in lowercase
@@ -42,22 +41,16 @@ def query_positive_negative(question_string: str,
42
41
 
43
42
  # If the gathered value is in "Yes" answers array
44
43
  if choice in positive_answers:
45
- # "right_answer" variable is True, so the loop will not execute again
46
- right_answer = True
47
44
  # Function will return True
48
45
  return True
49
46
  # Else If the gathered value is in "No" answers array
50
47
  elif choice in negative_answers:
51
- # "right_answer" variable is True, so the loop will not execute again
52
- right_answer = True
53
48
  # Function will return False
54
49
  return False
55
50
  # If the gathered input is not in the arrays
56
51
  else:
57
52
  # Then output to console the message
58
53
  print("Please respond with either:", positive_answers, negative_answers)
59
- # "right_answer" variable stays False, so the loop will execute again
60
- right_answer = False
61
54
 
62
55
 
63
56
  def do_you_want_to_continue_yn(message: str) -> None:
@@ -0,0 +1,27 @@
1
+ from typing import Union
2
+
3
+
4
+ def is_target_newer(
5
+ base_version: Union[str, tuple],
6
+ target_version: Union[str, tuple]
7
+ ):
8
+ """
9
+ Check if the target version is newer than the base version.
10
+ Example: is_target_newer('1.0.0', '1.0.1') -> True
11
+ Example: is_target_newer('1.0.0', '1.0.0') -> False
12
+ Example: is_target_newer('1.0.1', '1.0.0') -> False
13
+ Example: is_target_newer('1.0.1', '1.0.2') -> True
14
+ Example: is_target_newer((1,0,1), (1,1,0)) -> True
15
+
16
+ :param base_version: The base version to compare against.
17
+ :param target_version: The target version to compare.
18
+ """
19
+
20
+ # Convert string to tuple if string was passed.
21
+ if isinstance(base_version, str):
22
+ base_version = tuple(map(int, base_version.split('.')))
23
+ if isinstance(target_version, str):
24
+ target_version = tuple(map(int, target_version.split('.')))
25
+
26
+ # Compare the versions.
27
+ return target_version > base_version
atomicshop/web.py CHANGED
@@ -233,6 +233,8 @@ def download(
233
233
 
234
234
  if aggregated_bytes_int == file_size_bytes_int:
235
235
  print_api.print_api(f'Successfully Downloaded to: {file_path}', color="green", **kwargs)
236
+ elif file_size_bytes_int is None:
237
+ pass
236
238
  else:
237
239
  message = f'Download failed: {aggregated_bytes_int} / {file_size_bytes_int}. File: {file_path}'
238
240
  print_api.print_api(
@@ -1,7 +1,10 @@
1
1
  import requests
2
2
  import fnmatch
3
+ import os
4
+ import tempfile
5
+ from typing import Literal
3
6
 
4
- from .. import web, urls
7
+ from .. import web, urls, filesystem
5
8
  from ..print_api import print_api
6
9
 
7
10
 
@@ -21,7 +24,9 @@ class GitHubWrapper:
21
24
  branch: str = 'master',
22
25
  path: str = None,
23
26
  pat: str = None,
24
- branch_file_extension: str = '.zip'
27
+ branch_file_extension: Literal[
28
+ 'zip',
29
+ 'tar.gz'] = 'zip'
25
30
  ):
26
31
  """
27
32
  This class is a wrapper for GitHub repositories. It can download the branch file from the repository and extract
@@ -37,8 +42,8 @@ class GitHubWrapper:
37
42
  :param path: str, the path to the file/folder inside the repo that we'll do certain actions on.
38
43
  Actions example: get_latest_commit_comment, download_path_from_branch.
39
44
  :param pat: str, the personal access token to the repo.
40
- :param branch_file_extension: str, the branch file extension. The default is '.zip'.
41
- You also can use '.tar.gz' as extension.
45
+ :param branch_file_extension: str, the branch file extension. The default is 'zip'.
46
+ You also can use 'tar.gz' as extension.
42
47
 
43
48
  ================================================================================================================
44
49
  Usage to download the 'master' branch file:
@@ -93,13 +98,19 @@ class GitHubWrapper:
93
98
  self.branch_file_extension: str = branch_file_extension
94
99
 
95
100
  # Default variables.
96
- self.archive_directory: str = 'archive'
97
- self.branch_file_name: str = f'{self.branch}{self.branch_file_extension}'
101
+ if self.branch_file_extension == 'zip':
102
+ self.branch_type_directory: str = 'zipball'
103
+ elif self.branch_file_extension == 'tar.gz':
104
+ self.branch_type_directory: str = 'tarball'
105
+ else:
106
+ raise ValueError(f"Unsupported branch file extension: {self.branch_file_extension}")
107
+
98
108
  self.domain: str = 'github.com'
99
109
 
100
110
  # Initialize variables.
101
111
  self.branch_download_link: str = str()
102
112
  self.branch_downloaded_folder_name: str = str()
113
+ self.branch_file_name: str = str()
103
114
  self.api_url: str = str()
104
115
  self.latest_release_json_url: str = str()
105
116
  self.commits_url: str = str()
@@ -126,14 +137,15 @@ class GitHubWrapper:
126
137
  raise ValueError("'user_name' or 'repo_name' is empty.")
127
138
 
128
139
  self.repo_url = f'https://{self.domain}/{self.user_name}/{self.repo_name}'
129
- self.branch_download_link = f'{self.repo_url}/{self.archive_directory}/{self.branch_file_name}'
130
140
  self.branch_downloaded_folder_name = f'{self.repo_name}-{self.branch}'
141
+ self.branch_file_name: str = f'{self.repo_name}-{self.branch}.{self.branch_file_extension}'
131
142
 
132
143
  self.api_url = f'https://api.{self.domain}/repos/{self.user_name}/{self.repo_name}'
133
144
 
134
145
  self.latest_release_json_url: str = f'{self.api_url}/releases/latest'
135
146
  self.commits_url: str = f'{self.api_url}/commits'
136
147
  self.contents_url: str = f'{self.api_url}/contents'
148
+ self.branch_download_link = f'{self.api_url}/{self.branch_type_directory}/{self.branch}'
137
149
 
138
150
  def build_links_from_repo_url(self, **kwargs):
139
151
  if not self.repo_url:
@@ -178,48 +190,88 @@ class GitHubWrapper:
178
190
  :return:
179
191
  """
180
192
 
181
- headers: dict = self._get_headers()
193
+ def download_file(file_url: str, target_dir: str, file_name: str, current_headers: dict) -> None:
194
+ os.makedirs(target_dir, exist_ok=True)
182
195
 
183
- if not download_each_file:
184
- # Download the repo to current working directory, extract and remove the archive.
185
- web.download_and_extract_file(
186
- file_url=self.branch_download_link,
187
- target_directory=target_directory,
188
- archive_remove_first_directory=archive_remove_first_directory,
189
- headers=headers,
190
- **kwargs)
191
- else:
192
- # Build the URL for the contents API
193
- contents_url = f"{self.contents_url}/{self.path}"
196
+ web.download(
197
+ file_url=file_url,
198
+ target_directory=target_dir,
199
+ file_name=file_name,
200
+ headers=current_headers
201
+ )
202
+
203
+ def download_directory(folder_path: str, target_dir: str, current_headers: dict) -> None:
204
+ # Construct the API URL for the current folder.
205
+ contents_url = f"{self.contents_url}/{folder_path}"
194
206
  params = {'ref': self.branch}
195
207
 
196
- response = requests.get(contents_url, headers=headers, params=params)
208
+ response = requests.get(contents_url, headers=current_headers, params=params)
197
209
  response.raise_for_status()
198
210
 
211
+ # Get the list of items (files and subdirectories) in the folder.
199
212
  items = response.json()
200
213
 
201
- # Ensure the target directory exists.
202
- os.makedirs(target_directory, exist_ok=True)
214
+ # Ensure the local target directory exists.
215
+ os.makedirs(target_dir, exist_ok=True)
203
216
 
217
+ # Process each item.
204
218
  for item in items:
205
- item_path = os.path.join(target_directory, item['name'])
219
+ local_item_path = os.path.join(target_dir, item['name'])
206
220
  if item['type'] == 'file':
207
- # Download the file using the provided download URL.
208
- file_url = item['download_url']
209
- # You can reuse your download function here, passing the headers.
210
- download(
211
- file_url=file_url,
212
- target_directory=target_directory,
221
+ download_file(
222
+ file_url=item['download_url'],
223
+ target_dir=target_dir,
213
224
  file_name=item['name'],
214
- headers=headers
225
+ current_headers=current_headers
215
226
  )
216
227
  elif item['type'] == 'dir':
217
228
  # Recursively download subdirectories.
218
- self.download_folder_contents(
219
- folder_path=os.path.join(folder_path, item['name']),
220
- target_directory=item_path
229
+ download_directory(
230
+ folder_path=f"{folder_path}/{item['name']}",
231
+ target_dir=local_item_path,
232
+ current_headers=current_headers
221
233
  )
222
234
 
235
+ headers: dict = self._get_headers()
236
+
237
+ if not download_each_file:
238
+ if self.path:
239
+ download_target_directory = tempfile.mkdtemp()
240
+ current_archive_remove_first_directory = True
241
+ else:
242
+ download_target_directory = target_directory
243
+ current_archive_remove_first_directory = archive_remove_first_directory
244
+
245
+ # Download the repo to current working directory, extract and remove the archive.
246
+ web.download_and_extract_file(
247
+ file_url=self.branch_download_link,
248
+ file_name=self.branch_file_name,
249
+ target_directory=download_target_directory,
250
+ archive_remove_first_directory=current_archive_remove_first_directory,
251
+ headers=headers,
252
+ **kwargs)
253
+
254
+ if self.path:
255
+ source_path: str = f"{download_target_directory}{os.sep}{self.path}"
256
+
257
+ if not archive_remove_first_directory:
258
+ target_directory = os.path.join(target_directory, self.path)
259
+ filesystem.create_directory(target_directory)
260
+
261
+ # Move the path to the target directory.
262
+ filesystem.move_folder_contents_to_folder(
263
+ source_path, target_directory)
264
+
265
+ # Remove the downloaded branch directory.
266
+ filesystem.remove_directory(download_target_directory)
267
+ else:
268
+ if archive_remove_first_directory:
269
+ current_target_directory = target_directory
270
+ else:
271
+ current_target_directory = os.path.join(target_directory, self.path)
272
+
273
+ download_directory(self.path, current_target_directory, headers)
274
+
223
275
  def get_latest_release_url(
224
276
  self,
225
277
  string_pattern: str,
@@ -430,8 +482,7 @@ def github_wrapper_main(
430
482
 
431
483
  if download_branch:
432
484
  git_wrapper.download_and_extract_branch(
433
- target_directory=target_directory, download_each_file=True, download_branch_and_extract=False,
434
- archive_remove_first_directory=True)
485
+ target_directory=target_directory, download_each_file=False, archive_remove_first_directory=True)
435
486
 
436
487
  return 0
437
488
 
@@ -445,5 +496,6 @@ def github_wrapper_main_with_args():
445
496
  path=args.path,
446
497
  target_directory=args.target_directory,
447
498
  pat=args.pat,
448
- get_latest_commit_comment=args.get_latest_commit_comment
499
+ get_latest_commit_comment=args.get_latest_commit_comment,
500
+ download_branch=args.download_branch
449
501
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.19.11
3
+ Version: 2.19.12
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
- atomicshop/__init__.py,sha256=mHi1iDugkcLgj5LyCc_4EL-QVNq95QCoQWv522BGF1c,124
1
+ atomicshop/__init__.py,sha256=XtGdtCQBXBDdG8_6wWA54tuzPJ5IE_hCw_e_N2FoXLM,124
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
@@ -7,7 +7,7 @@ atomicshop/certificates.py,sha256=MEGj7t3Nt2CHE7yzXrvFTLCOKZG9tJ6Ok5JC2BsFRis,76
7
7
  atomicshop/command_line_processing.py,sha256=u5yT9Ger_cu7ni5ID0VFlRbVD46ARHeNC9tRM-_YXrQ,1038
8
8
  atomicshop/config_init.py,sha256=50kD2lXP8sgwPekcmAbfADcY46YvXkF-6XIdA7W_638,2501
9
9
  atomicshop/console_output.py,sha256=AOSJjrRryE97PAGtgDL03IBtWSi02aNol8noDnW3k6M,4667
10
- atomicshop/console_user_response.py,sha256=31HIy9QGXa7f-GVR8MzJauQ79E_ZqAeagF3Ks4GGdDU,3234
10
+ atomicshop/console_user_response.py,sha256=OHcjuzWAys6WmfRnMIU_nkJA634kKmJh6T8w1VtUTJM,2714
11
11
  atomicshop/datetimes.py,sha256=IQZ66lmta-ZqxYbyHzm_9eugbJFSilXK1e0kfMgoXGg,18371
12
12
  atomicshop/diff_check.py,sha256=vxTDccVbGZHEge6Ja9_ArLWwslOUgIoJAdYPylh4cZg,27176
13
13
  atomicshop/dns.py,sha256=5Gimq_WY2arqg7BeGmR7P--fGfnH0Dsh8lrOt_H0jRY,6817
@@ -44,8 +44,9 @@ atomicshop/timer.py,sha256=7Zw1KRV0acHCRATMnanyX2MLBb63Hc-6us3rCZ9dNlY,2345
44
44
  atomicshop/urls.py,sha256=aJ0NGS9qqaKeqjkkWBs80jaBBg6MYBiPuLIyPGxscVc,1557
45
45
  atomicshop/uuids.py,sha256=JSQdm3ZTJiwPQ1gYe6kU0TKS_7suwVrHc8JZDGYlydM,2214
46
46
  atomicshop/venvs.py,sha256=D9lwOoObkYoRx-weuoAmbvN-RdSHhVm4DE9TVl-utAs,903
47
+ atomicshop/versioning.py,sha256=e5W6m9AF3__M5nntqI9CqNAeHqkwY9JhlnpYeZ1CEus,970
47
48
  atomicshop/virtualization.py,sha256=LPP4vjE0Vr10R6DA4lqhfX_WaNdDGRAZUW0Am6VeGco,494
48
- atomicshop/web.py,sha256=No3hExQis7cmMay0GdHULG67RMLd5txg-3a-C7CWMd0,12052
49
+ atomicshop/web.py,sha256=uIYt1WHXllc2wwnsW4AOI_IrAEm9j89qAQa4v3nR8Wk,12105
49
50
  atomicshop/websocket_parse.py,sha256=aLHWyKqaYqEn_MRBWm2L6rIl6QPmqbVrjEXE_rBzwCw,16711
50
51
  atomicshop/a_installs/ubuntu/docker_rootless.py,sha256=9IPNtGZYjfy1_n6ZRt7gWz9KZgR6XCgevjqq02xk-o0,281
51
52
  atomicshop/a_installs/ubuntu/docker_sudo.py,sha256=JzayxeyKDtiuT4Icp2L2LyFRbx4wvpyN_bHLfZ-yX5E,281
@@ -192,7 +193,7 @@ atomicshop/wrappers/astw.py,sha256=VkYfkfyc_PJLIOxByT6L7B8uUmKY6-I8XGZl4t_z828,4
192
193
  atomicshop/wrappers/configparserw.py,sha256=JwDTPjZoSrv44YKwIRcjyUnpN-FjgXVfMqMK_tJuSgU,22800
193
194
  atomicshop/wrappers/cryptographyw.py,sha256=LfzTnwvJE03G6WZryOOf43VKhhnyMakzHpn8DPPCoy4,13252
194
195
  atomicshop/wrappers/ffmpegw.py,sha256=wcq0ZnAe0yajBOuTKZCCaKI7CDBjkq7FAgdW5IsKcVE,6031
195
- atomicshop/wrappers/githubw.py,sha256=razdRRkO-f00-E0cZs7LE8qoLd-Mm8hLOWlqKR3Ng0U,20343
196
+ atomicshop/wrappers/githubw.py,sha256=vaVQg0pkHY63_TfIbCoWmHDPtI2rDPAqMYwsOl3GN78,22559
196
197
  atomicshop/wrappers/msiw.py,sha256=GQLqud72nfex3kvO1bJSruNriCYTYX1_G1gSf1MPkIA,6118
197
198
  atomicshop/wrappers/numpyw.py,sha256=sBV4gSKyr23kXTalqAb1oqttzE_2XxBooCui66jbAqc,1025
198
199
  atomicshop/wrappers/olefilew.py,sha256=biD5m58rogifCYmYhJBrAFb9O_Bn_spLek_9HofLeYE,2051
@@ -328,8 +329,8 @@ atomicshop/wrappers/socketw/statistics_csv.py,sha256=fgMzDXI0cybwUEqAxprRmY3lqbh
328
329
  atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
329
330
  atomicshop/wrappers/winregw/winreg_installed_software.py,sha256=Qzmyktvob1qp6Tjk2DjLfAqr_yXV0sgWzdMW_9kwNjY,2345
330
331
  atomicshop/wrappers/winregw/winreg_network.py,sha256=AENV88H1qDidrcpyM9OwEZxX5svfi-Jb4N6FkS1xtqA,8851
331
- atomicshop-2.19.11.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
332
- atomicshop-2.19.11.dist-info/METADATA,sha256=tSnPcFSBceRSRX3c335xVMPu5zruA6fmE8ifV12MW-8,10631
333
- atomicshop-2.19.11.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
334
- atomicshop-2.19.11.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
335
- atomicshop-2.19.11.dist-info/RECORD,,
332
+ atomicshop-2.19.12.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
333
+ atomicshop-2.19.12.dist-info/METADATA,sha256=IjBkWX6cc09byHYWcjX8hdW_eEmXddbKu1h0hNYUybM,10631
334
+ atomicshop-2.19.12.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
335
+ atomicshop-2.19.12.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
336
+ atomicshop-2.19.12.dist-info/RECORD,,