python-base-toolkit 0.0.1__py3-none-any.whl → 0.0.2__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.
@@ -0,0 +1,4 @@
1
+ class Platform:
2
+ WINDOWS = "Windows"
3
+ LINUX = "Linux"
4
+ MACOS = "macOS"
@@ -2,6 +2,6 @@ import python_base_toolkit.consts.units.binary_units
2
2
  import python_base_toolkit.consts.units.time_units
3
3
 
4
4
  __all__ = [
5
- 'binary_units',
6
- 'time_units',
5
+ "binary_units",
6
+ "time_units",
7
7
  ]
@@ -7,7 +7,7 @@ PiB = TiB * 1024
7
7
  EiB = PiB * 1024
8
8
 
9
9
  KB = 1000 # 1 kilobyte (KB) = 1000 bytes in decimal (SI)
10
- GB = 1000 ** 3 # 1 gigabyte (GB) = 1000^3 bytes in decimal (SI)
11
- TB = 1000 ** 4 # 1 terabyte (TB) = 1000^4 bytes in decimal (SI)
12
- PB = 1000 ** 5 # 1 petabyte (PB) = 1000^5 bytes in decimal (SI)
13
- EB = 1000 ** 6 # 1 exabyte (EB) = 1000^6 bytes in decimal (SI)
10
+ GB = 1000**3 # 1 gigabyte (GB) = 1000^3 bytes in decimal (SI)
11
+ TB = 1000**4 # 1 terabyte (TB) = 1000^4 bytes in decimal (SI)
12
+ PB = 1000**5 # 1 petabyte (PB) = 1000^5 bytes in decimal (SI)
13
+ EB = 1000**6 # 1 exabyte (EB) = 1000^6 bytes in decimal (SI)
@@ -1,8 +1,9 @@
1
+ import datetime
1
2
  import json
2
3
  import time
4
+ from collections.abc import Callable
3
5
  from functools import wraps
4
- import datetime
5
- from typing import Callable, Any
6
+ from typing import Any
6
7
 
7
8
  from custom_python_logger import get_logger
8
9
 
@@ -10,11 +11,7 @@ logger = get_logger(__name__)
10
11
 
11
12
 
12
13
  def report_telemetry(
13
- func: Callable[..., Any],
14
- start_time: datetime.datetime,
15
- end_time: datetime.datetime,
16
- *args: Any,
17
- **kwargs: Any
14
+ func: Callable[..., Any], start_time: datetime.datetime, end_time: datetime.datetime, *args: Any, **kwargs: Any
18
15
  ) -> None:
19
16
  data = {
20
17
  "function_name": func.__name__,
@@ -25,7 +22,8 @@ def report_telemetry(
25
22
  "timestamp": time.time(),
26
23
  }
27
24
  logger.info(
28
- f"Sending telemetry data with the following data: {json.dumps(data, indent=4, sort_keys=False, default=str)}")
25
+ f"Sending telemetry data with the following data: {json.dumps(data, indent=4, sort_keys=False, default=str)}"
26
+ )
29
27
 
30
28
 
31
29
  def report_func_telemetry(func: Callable[..., Any]) -> Callable[..., Any]:
@@ -37,7 +35,7 @@ def report_func_telemetry(func: Callable[..., Any]) -> Callable[..., Any]:
37
35
  start_time = datetime.datetime.now(datetime.UTC)
38
36
  result = func(*args, **kwargs)
39
37
  end_time = datetime.datetime.now(datetime.UTC)
40
- report_telemetry(func=func, start_time=start_time, end_time=end_time, *args, **kwargs)
38
+ report_telemetry(*args, func=func, start_time=start_time, end_time=end_time, **kwargs)
41
39
  return result
42
40
 
43
41
  return wrapper
@@ -1,6 +1,7 @@
1
1
  import time
2
+ from collections.abc import Callable
2
3
  from functools import wraps
3
- from typing import Callable, Any
4
+ from typing import Any
4
5
 
5
6
  from custom_python_logger import get_logger
6
7
 
@@ -8,12 +9,17 @@ logger = get_logger(__name__)
8
9
 
9
10
 
10
11
  class Timer:
11
- def __enter__(self):
12
+ def __init__(self) -> None:
13
+ self.start_time = None
14
+ self.end_time = None
15
+ self.elapsed_time = None
16
+
17
+ def __enter__(self) -> "Timer":
12
18
  self.start_time = time.perf_counter()
13
19
  logger.info("Timer started.")
14
20
  return self
15
21
 
16
- def __exit__(self, exc_type, exc_value, exc_traceback):
22
+ def __exit__(self, exc_type: type, exc_value: Exception, exc_traceback: object) -> None:
17
23
  # logger.info(exc_type, exc_value, exc_traceback)
18
24
  self.end_time = time.perf_counter()
19
25
  self.elapsed_time = self.end_time - self.start_time
@@ -25,4 +31,5 @@ def timer(func: Callable[..., Any]) -> Callable[..., Any]:
25
31
  def wrapper(*args: Any, **kwargs: Any) -> Any:
26
32
  with Timer():
27
33
  return func(*args, **kwargs)
34
+
28
35
  return wrapper
@@ -1,18 +1,19 @@
1
1
  from custom_python_logger.logger import get_logger
2
2
 
3
+
3
4
  class InstanceManager:
4
- def __init__(self):
5
+ def __init__(self) -> None:
5
6
  self.logger = get_logger(__class__.__name__)
6
7
  self._instances = []
7
8
 
8
- def add(self, instance):
9
+ def add(self, instance: object) -> None:
9
10
  self._instances.append(instance)
10
11
 
11
- def close_all(self):
12
+ def close_all(self) -> None:
12
13
  for instance in reversed(self._instances):
13
14
  _instance_name = instance.__class__.__name__
14
15
  try:
15
- if hasattr(instance, 'close'):
16
+ if hasattr(instance, "close"):
16
17
  instance.close()
17
18
  else: # hasattr(instance, '__exit__'):
18
19
  instance.__exit__(None, None, None)
@@ -20,31 +21,31 @@ class InstanceManager:
20
21
  except Exception as e:
21
22
  self.logger.info(f"Failed to close instance {instance}: {e}")
22
23
 
23
- def __enter__(self):
24
+ def __enter__(self) -> "InstanceManager":
24
25
  return self
25
26
 
26
- def __exit__(self, exc_type, exc_value, traceback):
27
+ def __exit__(self, exc_type: type, exc_value: Exception, traceback: object) -> None:
27
28
  self.close_all()
28
29
 
29
30
 
30
- def main():
31
+ def main() -> None:
31
32
  class SomeInstance:
32
- def __init__(self, add_to_instance_manager: bool = False):
33
+ def __init__(self, add_to_instance_manager: bool = False) -> None:
33
34
  self.logger = get_logger(__class__.__name__)
34
35
 
35
36
  if add_to_instance_manager:
36
- instance_manager.add(self)
37
+ instance_manager.add(self) # pylint: disable=E0601
37
38
 
38
39
  @property
39
- def __class_name__(self):
40
+ def class_name(self) -> str:
40
41
  return self.__class__.__name__
41
42
 
42
- def __enter__(self):
43
- self.logger.info(f"Entering {self.__class_name__}")
43
+ def __enter__(self) -> "SomeInstance":
44
+ self.logger.info(f"Entering {self.class_name}")
44
45
  return self
45
46
 
46
- def __exit__(self, exc_type, exc_value, exc_traceback):
47
- self.logger.info(f"Exiting {self.__class_name__}")
47
+ def __exit__(self, exc_type: type, exc_value: Exception, traceback: object) -> bool:
48
+ self.logger.info(f"Exiting {self.class_name}")
48
49
  # Handle any cleanup here
49
50
  if exc_type:
50
51
  self.logger.info(f"Exception: {exc_value}")
@@ -52,8 +53,8 @@ def main():
52
53
 
53
54
  SomeInstance(add_to_instance_manager=True)
54
55
 
55
- resource1 = open('file1.txt', 'w')
56
- resource2 = open('file2.txt', 'w')
56
+ resource1 = open("file1.txt", "w") # pylint: disable=R1732
57
+ resource2 = open("file2.txt", "w") # pylint: disable=R1732
57
58
 
58
59
  instance_manager.add(resource1)
59
60
  instance_manager.add(resource2)
@@ -1,6 +1,6 @@
1
1
  import json
2
2
  from dataclasses import is_dataclass
3
- from datetime import datetime, date, time
3
+ from datetime import date, datetime, time
4
4
  from decimal import Decimal
5
5
  from enum import Enum
6
6
  from pathlib import Path
@@ -23,7 +23,7 @@ def default_serialize(obj: object) -> object:
23
23
  return list(obj)
24
24
  if isinstance(obj, tuple):
25
25
  return list(obj)
26
- if isinstance(obj, (datetime, date, time)):
26
+ if isinstance(obj, datetime | date | time):
27
27
  return obj.isoformat()
28
28
  if isinstance(obj, Decimal):
29
29
  return float(obj)
@@ -31,7 +31,7 @@ def default_serialize(obj: object) -> object:
31
31
  return str(obj)
32
32
  if obj is pd.NA:
33
33
  return None
34
- logger.error(f'Object is not serializable: {obj}')
34
+ logger.error(f"Object is not serializable: {obj}")
35
35
  raise TypeError(f"Type {type(obj)} not serializable")
36
36
 
37
37
 
@@ -1,7 +1,7 @@
1
1
  from datetime import datetime
2
2
  from zoneinfo import ZoneInfo
3
3
 
4
- utc_timezone = ZoneInfo('UTC')
4
+ utc_timezone = ZoneInfo("UTC")
5
5
 
6
6
 
7
7
  def datetime_now_with_timezone(timezone: ZoneInfo = utc_timezone) -> datetime:
@@ -9,6 +9,6 @@ def datetime_now_with_timezone(timezone: ZoneInfo = utc_timezone) -> datetime:
9
9
  raise TypeError(f"Expected pytz timezone, got {type(timezone).__name__}")
10
10
 
11
11
  now_utc = datetime.now(timezone)
12
- if timezone.key == 'UTC':
12
+ if timezone.key == "UTC":
13
13
  return now_utc
14
14
  return now_utc.astimezone(timezone)
@@ -16,7 +16,7 @@ def _timed_execution(
16
16
  pbar = tqdm(total=timeout, desc=pb_description, unit="s", ncols=100)
17
17
  start_time = time()
18
18
 
19
- while time() - start_time < timeout:
19
+ while time() - start_time < timeout: # pylint: disable=W0149
20
20
  res = func()
21
21
  if (expect_true and res) or (not expect_true and not res):
22
22
  pbar.close()
@@ -1,256 +1,263 @@
1
+ import csv
1
2
  import gzip
2
- import os
3
3
  import hashlib
4
- import shutil
5
4
  import json
6
- import csv
7
- import yaml
5
+ import os
8
6
  import re
9
- from typing import Optional, Union, BinaryIO, TextIO, cast, Any
7
+ import shutil
10
8
  import tarfile
11
9
  import zipfile
10
+ from typing import Any, BinaryIO, TextIO, cast
12
11
 
12
+ import yaml
13
13
  from custom_python_logger import get_logger
14
14
 
15
15
  logger = get_logger(__name__)
16
16
 
17
17
 
18
- class FilePath:
18
+ class _FileCompression:
19
19
  @staticmethod
20
- def ensure_dir(directory: str) -> str:
21
- if not os.path.exists(directory):
22
- os.makedirs(directory)
23
- return directory
20
+ def gzip_file(input_path: str, output_path: str | None = None) -> str:
21
+ if not os.path.isfile(input_path):
22
+ raise FileNotFoundError(f"Input file does not exist: {input_path}")
23
+
24
+ if output_path is None:
25
+ output_path = input_path + ".gz"
26
+
27
+ try:
28
+ with open(input_path, "rb") as f_in:
29
+ with gzip.open(output_path, "wb") as f_out:
30
+ f_out.write(f_in.read())
31
+ return output_path
32
+ except Exception as e:
33
+ raise OSError(f"Error compressing file: {e}") from e
24
34
 
25
35
  @staticmethod
26
- def file_exists(path: str) -> bool:
27
- return os.path.isfile(path)
36
+ def ungzip_file(gz_path: str, output_path: str | None = None) -> str:
37
+ if not os.path.isfile(gz_path):
38
+ raise FileNotFoundError(f"Gzipped file does not exist: {gz_path}")
39
+
40
+ if output_path is None:
41
+ if gz_path.endswith(".gz"):
42
+ output_path = gz_path[:-3] # Remove .gz extension
43
+ else:
44
+ output_path = gz_path + "_decompressed"
45
+
46
+ try:
47
+ with gzip.open(gz_path, "rb") as f_in:
48
+ with open(output_path, "wb") as f_out:
49
+ f_out.write(f_in.read())
50
+ return output_path
51
+ except Exception as e:
52
+ raise OSError(f"Error decompressing file: {e}") from e
28
53
 
29
54
  @staticmethod
30
- def get_file_extension(path: str) -> str:
31
- return os.path.splitext(path)[1][1:]
55
+ def compress_directory(directory: str, output_path: str | None = None) -> str:
56
+ """Compress directory to tarball."""
57
+ if not os.path.isdir(directory):
58
+ raise FileNotFoundError(f"Directory does not exist: {directory}")
59
+
60
+ if output_path is None:
61
+ output_path = directory.rstrip(os.sep) + ".tar.gz"
62
+
63
+ with tarfile.open(output_path, "w:gz") as tar:
64
+ tar.add(directory, arcname=os.path.basename(directory))
65
+
66
+ return output_path
32
67
 
33
68
  @staticmethod
34
- def get_filename(path: str, with_extension: bool = True) -> str:
35
- if with_extension:
36
- return os.path.basename(path)
37
- return os.path.splitext(os.path.basename(path))[0]
69
+ def extract_archive(archive_path: str, output_dir: str | None = None) -> str:
70
+ """Extract archive file."""
71
+ if not os.path.isfile(archive_path):
72
+ raise FileNotFoundError(f"Archive does not exist: {archive_path}")
38
73
 
74
+ if output_dir is None:
75
+ output_dir = os.path.splitext(archive_path)[0]
76
+ # Handle double extensions like .tar.gz
77
+ if output_dir.endswith(".tar"):
78
+ output_dir = output_dir[:-4]
79
+
80
+ _FilePath.ensure_dir(output_dir)
81
+
82
+ if archive_path.endswith((".tar.gz", ".tgz")):
83
+ with tarfile.open(archive_path, "r:gz") as tar:
84
+ tar.extractall(path=output_dir)
85
+ elif archive_path.endswith(".tar.bz2"):
86
+ with tarfile.open(archive_path, "r:bz2") as tar:
87
+ tar.extractall(path=output_dir)
88
+ elif archive_path.endswith(".tar"):
89
+ with tarfile.open(archive_path, "r") as tar:
90
+ tar.extractall(path=output_dir)
91
+ elif archive_path.endswith(".zip"):
92
+ with zipfile.ZipFile(archive_path, "r") as zip_ref:
93
+ zip_ref.extractall(output_dir)
94
+ else:
95
+ raise ValueError(f"Unsupported archive format: {archive_path}")
96
+
97
+ return output_dir
98
+
99
+
100
+ class _FileHash:
39
101
  @staticmethod
40
- def get_relative_path(path: str, base_path: str) -> str:
41
- return os.path.relpath(path, base_path)
102
+ def file_md5(filename: str, chunk_size: int = 8192) -> str:
103
+ """Calculate MD5 hash of a file."""
104
+ hash_md5 = hashlib.md5()
105
+ with open(filename, "rb") as f:
106
+ for chunk in iter(lambda: f.read(chunk_size), b""):
107
+ hash_md5.update(chunk)
108
+ return hash_md5.hexdigest()
42
109
 
43
110
  @staticmethod
44
- def list_files(directory: str, extension: Optional[str] = None, recursive: bool = False) -> list[str]:
45
- result = []
46
- for root, _, files in os.walk(directory) if recursive else [(directory, [], os.listdir(directory))]:
47
- for file in files:
48
- if not extension or file.endswith(extension):
49
- result.append(os.path.join(root, file))
50
- return result
111
+ def file_sha1(filename: str, chunk_size: int = 8192) -> str:
112
+ """Calculate SHA1 hash of a file."""
113
+ hash_sha1 = hashlib.sha1()
114
+ with open(filename, "rb") as f:
115
+ for chunk in iter(lambda: f.read(chunk_size), b""):
116
+ hash_sha1.update(chunk)
117
+ return hash_sha1.hexdigest()
118
+
119
+ @staticmethod
120
+ def file_sha256(filename: str, chunk_size: int = 8192) -> str:
121
+ """Calculate SHA256 hash of a file."""
122
+ hash_sha256 = hashlib.sha256()
123
+ with open(filename, "rb") as f:
124
+ for chunk in iter(lambda: f.read(chunk_size), b""):
125
+ hash_sha256.update(chunk)
126
+ return hash_sha256.hexdigest()
51
127
 
52
128
 
53
- class FileIO:
129
+ class _FileIO:
54
130
  @staticmethod
55
- def safe_open(
56
- filename: str,
57
- mode: str = 'r',
58
- encoding: Optional[str] = None,
59
- **kwargs
60
- ) -> Union[TextIO, BinaryIO]:
61
- if 'b' in mode:
131
+ def safe_open(filename: str, mode: str = "r", encoding: str | None = None, **kwargs: Any) -> TextIO | BinaryIO:
132
+ if "b" in mode:
62
133
  return cast(BinaryIO, open(filename, mode, **kwargs))
63
- return cast(TextIO, open(filename, mode, encoding=encoding or 'utf-8', **kwargs))
134
+ return cast(TextIO, open(filename, mode, encoding=encoding or "utf-8", **kwargs))
64
135
 
65
136
  @staticmethod
66
- def read_text(filename: str, encoding: str = 'utf-8') -> str:
67
- with open(filename, 'r', encoding=encoding) as f:
137
+ def read_text(filename: str, encoding: str = "utf-8") -> str:
138
+ with open(filename, encoding=encoding) as f:
68
139
  return f.read()
69
140
 
70
141
  @staticmethod
71
- def write_text(text: str, filename: str, encoding: str = 'utf-8') -> None:
72
- with open(filename, 'w', encoding=encoding) as f:
142
+ def write_text(text: str, filename: str, encoding: str = "utf-8") -> None:
143
+ with open(filename, "w", encoding=encoding) as f:
73
144
  f.write(text)
74
145
 
75
- def read_json(self, filename: str) -> dict[str, Any]:
76
- with self.safe_open(filename, 'r') as f:
146
+ @staticmethod
147
+ def read_json(filename: str) -> dict[str, Any]:
148
+ with _FileIO.safe_open(filename, "r") as f:
77
149
  return json.load(f)
78
150
 
79
151
  @staticmethod
80
152
  def write_json(data: dict[str, Any], filename: str, indent: int = 2) -> None:
81
- with open(filename, 'w', encoding='utf-8') as f:
153
+ with open(filename, "w", encoding="utf-8") as f:
82
154
  json.dump(data, f, indent=indent, ensure_ascii=False)
83
155
 
84
156
  @staticmethod
85
157
  def read_yaml(filename: str) -> Any:
86
- with open(filename, 'r', encoding='utf-8') as f:
158
+ with open(filename, encoding="utf-8") as f:
87
159
  return yaml.safe_load(f)
88
160
 
89
161
  @staticmethod
90
- def write_yaml(data: Any, filename: str, **kwargs) -> None:
91
- with open(filename, 'w', encoding='utf-8') as f:
162
+ def write_yaml(data: Any, filename: str, **kwargs: Any) -> None:
163
+ with open(filename, "w", encoding="utf-8") as f:
92
164
  yaml.safe_dump(data, f, allow_unicode=True, **kwargs)
93
165
 
94
- def read_csv(self, filename: str, **kwargs) -> list[dict[str, Any]]:
95
- with self.safe_open(filename, 'r', newline='') as f:
166
+ def read_csv(self, filename: str, **kwargs: Any) -> list[dict[str, Any]]:
167
+ with self.safe_open(filename, "r", newline="") as f:
96
168
  reader = csv.DictReader(f, **kwargs)
97
169
  return list(reader)
98
170
 
99
171
  @staticmethod
100
- def write_csv(data: list[dict[str, Any]], filename: str, fieldnames: Optional[list[str]] = None, **kwargs) -> None:
172
+ def write_csv(
173
+ data: list[dict[str, Any]], filename: str, fieldnames: list[str] | None = None, **kwargs: Any
174
+ ) -> None:
101
175
  if not data:
102
176
  return
103
177
 
104
178
  if fieldnames is None:
105
179
  fieldnames = list(data[0].keys())
106
180
 
107
- with open(filename, 'w', newline='', encoding='utf-8') as f:
181
+ with open(filename, "w", newline="", encoding="utf-8") as f:
108
182
  writer = csv.DictWriter(f, fieldnames=fieldnames, **kwargs)
109
183
  writer.writeheader()
110
184
  writer.writerows(data)
111
185
 
112
186
  @staticmethod
113
187
  def is_binary_file(path: str, chunk_size: int = 1024) -> bool:
114
- with open(path, 'rb') as f:
188
+ with open(path, "rb") as f:
115
189
  chunk = f.read(chunk_size)
116
- return b'\0' in chunk
190
+ return b"\0" in chunk
117
191
 
118
192
  @staticmethod
119
193
  def is_file_empty(path: str) -> bool:
120
194
  return os.path.getsize(path) == 0
121
195
 
122
196
 
123
- class FfileManipulation:
197
+ class _FileManipulation:
124
198
  @staticmethod
125
199
  def remove_emojis(text: str) -> str:
126
- return re.sub(r'[\U00010000-\U0010ffff]', '', text).strip()
127
-
200
+ return re.sub(r"[\U00010000-\U0010ffff]", "", text).strip()
128
201
 
129
- class FileSystem:
130
- @staticmethod
131
- def copy_file(src: str, dst: str) -> None:
132
- shutil.copy2(src, dst)
133
202
 
203
+ class _FilePath:
134
204
  @staticmethod
135
- def move_file(src: str, dst: str) -> None:
136
- shutil.move(src, dst)
205
+ def ensure_dir(directory: str) -> str:
206
+ if not os.path.exists(directory):
207
+ os.makedirs(directory)
208
+ return directory
137
209
 
138
210
  @staticmethod
139
- def delete_file(path: str) -> None:
140
- if os.path.isfile(path):
141
- os.remove(path)
211
+ def file_exists(path: str) -> bool:
212
+ return os.path.isfile(path)
142
213
 
143
214
  @staticmethod
144
- def file_size(path: str) -> int:
145
- return os.path.getsize(path)
146
-
215
+ def get_file_extension(path: str) -> str:
216
+ return os.path.splitext(path)[1][1:]
147
217
 
148
- class FileHash:
149
218
  @staticmethod
150
- def file_md5(filename: str, chunk_size: int = 8192) -> str:
151
- """Calculate MD5 hash of a file."""
152
- hash_md5 = hashlib.md5()
153
- with open(filename, "rb") as f:
154
- for chunk in iter(lambda: f.read(chunk_size), b""):
155
- hash_md5.update(chunk)
156
- return hash_md5.hexdigest()
219
+ def get_filename(path: str, with_extension: bool = True) -> str:
220
+ if with_extension:
221
+ return os.path.basename(path)
222
+ return os.path.splitext(os.path.basename(path))[0]
157
223
 
158
224
  @staticmethod
159
- def file_sha1(filename: str, chunk_size: int = 8192) -> str:
160
- """Calculate SHA1 hash of a file."""
161
- hash_sha1 = hashlib.sha1()
162
- with open(filename, "rb") as f:
163
- for chunk in iter(lambda: f.read(chunk_size), b""):
164
- hash_sha1.update(chunk)
165
- return hash_sha1.hexdigest()
225
+ def get_relative_path(path: str, base_path: str) -> str:
226
+ return os.path.relpath(path, base_path)
166
227
 
167
228
  @staticmethod
168
- def file_sha256(filename: str, chunk_size: int = 8192) -> str:
169
- """Calculate SHA256 hash of a file."""
170
- hash_sha256 = hashlib.sha256()
171
- with open(filename, "rb") as f:
172
- for chunk in iter(lambda: f.read(chunk_size), b""):
173
- hash_sha256.update(chunk)
174
- return hash_sha256.hexdigest()
229
+ def list_files(directory: str, extension: str | None = None, recursive: bool = False) -> list[str]:
230
+ result = []
231
+ for root, _, files in os.walk(directory) if recursive else [(directory, [], os.listdir(directory))]:
232
+ for file in files:
233
+ if not extension or file.endswith(extension):
234
+ result.append(os.path.join(root, file))
235
+ return result
175
236
 
176
237
 
177
- class FileCompression:
238
+ class _FileSystem:
178
239
  @staticmethod
179
- def gzip_file(input_path: str, output_path: Optional[str] = None) -> str:
180
- if not os.path.isfile(input_path):
181
- raise FileNotFoundError(f"Input file does not exist: {input_path}")
182
-
183
- if output_path is None:
184
- output_path = input_path + '.gz'
185
-
186
- try:
187
- with open(input_path, 'rb') as f_in:
188
- with gzip.open(output_path, 'wb') as f_out:
189
- f_out.write(f_in.read())
190
- return output_path
191
- except Exception as e:
192
- raise IOError(f"Error compressing file: {e}")
240
+ def copy_file(src: str, dst: str) -> None:
241
+ shutil.copy2(src, dst)
193
242
 
194
243
  @staticmethod
195
- def ungzip_file(gz_path: str, output_path: Optional[str] = None) -> str:
196
- if not os.path.isfile(gz_path):
197
- raise FileNotFoundError(f"Gzipped file does not exist: {gz_path}")
198
-
199
- if output_path is None:
200
- if gz_path.endswith('.gz'):
201
- output_path = gz_path[:-3] # Remove .gz extension
202
- else:
203
- output_path = gz_path + '_decompressed'
204
-
205
- try:
206
- with gzip.open(gz_path, 'rb') as f_in:
207
- with open(output_path, 'wb') as f_out:
208
- f_out.write(f_in.read())
209
- return output_path
210
- except Exception as e:
211
- raise IOError(f"Error decompressing file: {e}")
244
+ def move_file(src: str, dst: str) -> None:
245
+ shutil.move(src, dst)
212
246
 
213
247
  @staticmethod
214
- def compress_directory(directory: str, output_path: Optional[str] = None) -> str:
215
- """Compress directory to tarball."""
216
- if not os.path.isdir(directory):
217
- raise FileNotFoundError(f"Directory does not exist: {directory}")
218
-
219
- if output_path is None:
220
- output_path = directory.rstrip(os.sep) + '.tar.gz'
221
-
222
- with tarfile.open(output_path, 'w:gz') as tar:
223
- tar.add(directory, arcname=os.path.basename(directory))
224
-
225
- return output_path
248
+ def delete_file(path: str) -> None:
249
+ if os.path.isfile(path):
250
+ os.remove(path)
226
251
 
227
252
  @staticmethod
228
- def extract_archive(archive_path: str, output_dir: Optional[str] = None) -> str:
229
- """Extract archive file."""
230
- if not os.path.isfile(archive_path):
231
- raise FileNotFoundError(f"Archive does not exist: {archive_path}")
232
-
233
- if output_dir is None:
234
- output_dir = os.path.splitext(archive_path)[0]
235
- # Handle double extensions like .tar.gz
236
- if output_dir.endswith('.tar'):
237
- output_dir = output_dir[:-4]
238
-
239
- FilePath.ensure_dir(output_dir)
253
+ def file_size(path: str) -> int:
254
+ return os.path.getsize(path)
240
255
 
241
- if archive_path.endswith(('.tar.gz', '.tgz')):
242
- with tarfile.open(archive_path, 'r:gz') as tar:
243
- tar.extractall(path=output_dir)
244
- elif archive_path.endswith('.tar.bz2'):
245
- with tarfile.open(archive_path, 'r:bz2') as tar:
246
- tar.extractall(path=output_dir)
247
- elif archive_path.endswith('.tar'):
248
- with tarfile.open(archive_path, 'r') as tar:
249
- tar.extractall(path=output_dir)
250
- elif archive_path.endswith('.zip'):
251
- with zipfile.ZipFile(archive_path, 'r') as zip_ref:
252
- zip_ref.extractall(output_dir)
253
- else:
254
- raise ValueError(f"Unsupported archive format: {archive_path}")
255
256
 
256
- return output_dir
257
+ class FileUtils:
258
+ file_compression = _FileCompression
259
+ file_hash = _FileHash
260
+ file_io = _FileIO
261
+ file_manipulation = _FileManipulation
262
+ file_path = _FilePath
263
+ file_system = _FileSystem
@@ -0,0 +1,35 @@
1
+ import random
2
+ import string
3
+ from datetime import datetime
4
+
5
+ from custom_python_logger import get_logger
6
+
7
+ logger = get_logger(__name__)
8
+
9
+
10
+ def generate_id(length: int = 8) -> str:
11
+ # helper function for generating an id
12
+ id_ = "".join(random.choices(string.ascii_uppercase, k=length))
13
+ logger.info(f"id is: {id_}")
14
+ return id_
15
+
16
+
17
+ def generate_id_by_date() -> str:
18
+ timestamp = datetime.now()
19
+ id_ = timestamp.strftime("%Y%m%d")
20
+ logger.info(f"id is: {id_}")
21
+ return id_
22
+
23
+
24
+ def generate_id_by_time() -> str:
25
+ timestamp = datetime.now()
26
+ id_ = timestamp.strftime("%H%M%S%m")
27
+ logger.info(f"id is: {id_}")
28
+ return id_
29
+
30
+
31
+ def generate_id_by_date_and_time() -> str:
32
+ timestamp = datetime.now()
33
+ id_ = timestamp.strftime("%Y%m%d%H%M%S%m")
34
+ logger.info(f"id is: {id_}")
35
+ return id_
@@ -1,6 +1,6 @@
1
1
  from pyfiglet import Figlet
2
2
 
3
3
 
4
- def create_logo(text: str, font: str = 'big') -> str:
4
+ def create_logo(text: str, font: str = "big") -> str:
5
5
  f = Figlet(font=font)
6
6
  return f.renderText(text)
@@ -1,9 +1,23 @@
1
1
  import ipaddress
2
+ import os
2
3
  import re
3
- from typing import Optional
4
4
 
5
+ from custom_python_logger import get_logger
5
6
 
6
- def get_ip_version(ip: str) -> Optional[int]:
7
+ from python_base_toolkit.consts.operating_system import Platform
8
+
9
+ logger = get_logger(__name__)
10
+
11
+
12
+ def is_ip_address(ip: str) -> bool:
13
+ try:
14
+ ipaddress.ip_address(ip)
15
+ return True
16
+ except ValueError:
17
+ return False
18
+
19
+
20
+ def get_ip_version(ip: str) -> int | None:
7
21
  """
8
22
  Returns the type of the IP address as integer (IPv4, IPv6 or None in case of an invalid IP address)
9
23
  :param ip: IP address (String)
@@ -15,7 +29,7 @@ def get_ip_version(ip: str) -> Optional[int]:
15
29
  return None
16
30
 
17
31
 
18
- def normalize_connection_string(ip: str, port: Optional[int] = None) -> str:
32
+ def normalize_connection_string(ip: str, port: int | None = None) -> str:
19
33
  """
20
34
  Returns a normalized connection string (IPv4:port or [IPv6]:port)
21
35
  :param ip: IP address (String)
@@ -25,25 +39,25 @@ def normalize_connection_string(ip: str, port: Optional[int] = None) -> str:
25
39
  w/ Port - IPv4:port or [IPv6]:port
26
40
  w/o Port - IPv4: or [IPv6]:
27
41
  """
28
- _operation = 'Normalize connection string'
42
+ _operation = "Normalize connection string"
29
43
 
30
44
  _ip_version = get_ip_version(ip)
31
45
  if _ip_version == 4:
32
46
  return f'{ip}:{port or ""}'
33
47
  if _ip_version == 6:
34
48
  return f'[{ip}]:{port or ""}'
35
- raise ValueError(f'Invalid IP address: {ip} - {_operation}')
49
+ raise ValueError(f"Invalid IP address: {ip} - {_operation}")
36
50
 
37
51
 
38
- def normalize_http_url(ip: str, port: Optional[int] = None, https: bool = True) -> str:
52
+ def normalize_http_url(ip: str, port: int | None = None, https: bool = True) -> str:
39
53
  """
40
54
  Returns a normalized HTTP URL (http://IPv4:port or http://[IPv6]:port)
41
55
  :param ip: IP address (String)
42
56
  :param port: Port (Integer)
43
57
  :param https: Use HTTPS (Boolean)
44
58
  """
45
- url_schema = 'https' if https else 'http'
46
- return f'{url_schema}://{normalize_connection_string(ip, port)}'
59
+ url_schema = "https" if https else "http"
60
+ return f"{url_schema}://{normalize_connection_string(ip, port)}"
47
61
 
48
62
 
49
63
  def parse_ifconfig_to_json(ifconfig_output: str) -> dict:
@@ -63,40 +77,70 @@ def parse_ifconfig_to_json(ifconfig_output: str) -> dict:
63
77
  current_interface = None
64
78
 
65
79
  for line in ifconfig_output.splitlines():
66
- match_interface = re.match(r'^(\S+):\s', line)
67
- if match_interface:
80
+ if match_interface := re.match("^(\\S+):\\s", line):
68
81
  current_interface = match_interface.group(1)
69
82
  interfaces[current_interface] = {}
70
83
 
71
- match_mac = re.search(r'ether\s([0-9a-f:]+)', line)
84
+ match_mac = re.search(r"ether\s([0-9a-f:]+)", line)
72
85
  if match_mac and current_interface:
73
- interfaces[current_interface]['mac_address'] = match_mac.group(1)
86
+ interfaces[current_interface]["mac_address"] = match_mac.group(1)
74
87
 
75
- match_ipv4 = re.search(r'inet\s(\d+\.\d+\.\d+\.\d+)', line)
88
+ match_ipv4 = re.search(r"inet\s(\d+\.\d+\.\d+\.\d+)", line)
76
89
  if match_ipv4 and current_interface:
77
- interfaces[current_interface]['ipv4_address'] = match_ipv4.group(1)
90
+ interfaces[current_interface]["ipv4_address"] = match_ipv4.group(1)
78
91
 
79
92
  # Try different netmask patterns
80
- match_netmask = re.search(r'netmask\s+(0x[0-9a-f]+|(?:\d+\.){3}\d+)', line, re.IGNORECASE)
93
+ match_netmask = re.search(r"netmask\s+(0x[0-9a-f]+|(?:\d+\.){3}\d+)", line, re.IGNORECASE)
81
94
  if match_netmask and current_interface:
82
95
  netmask = match_netmask.group(1)
83
- if netmask.startswith('0x'):
96
+ if netmask.startswith("0x"):
84
97
  # Handle hex format
85
98
  netmask_int = int(netmask, 16)
86
99
  else:
87
100
  # Handle decimal format (255.255.255.0)
88
- octets = [int(x) for x in netmask.split('.')]
101
+ octets = [int(x) for x in netmask.split(".")]
89
102
  netmask_int = sum(octet << (24 - 8 * i) for i, octet in enumerate(octets))
90
103
 
91
- binary_netmask = f'{netmask_int:032b}'
92
- interfaces[current_interface]['ipv4_netmask'] = binary_netmask.count('1')
104
+ binary_netmask = f"{netmask_int:032b}"
105
+ interfaces[current_interface]["ipv4_netmask"] = binary_netmask.count("1")
93
106
 
94
- match_ipv6 = re.search(r'inet6\s([0-9a-fA-F:]+)', line)
107
+ match_ipv6 = re.search(r"inet6\s([0-9a-fA-F:]+)", line)
95
108
  if match_ipv6 and current_interface:
96
- interfaces[current_interface]['ipv6_address'] = match_ipv6.group(1)
109
+ interfaces[current_interface]["ipv6_address"] = match_ipv6.group(1)
97
110
 
98
- match_subnet_mask = re.search(r'prefixlen\s([0-9a-f:]+)', line)
111
+ match_subnet_mask = re.search(r"prefixlen\s([0-9a-f:]+)", line)
99
112
  if match_subnet_mask and current_interface:
100
- interfaces[current_interface]['ipv6_prefixlen'] = match_subnet_mask.group(1)
113
+ interfaces[current_interface]["ipv6_prefixlen"] = match_subnet_mask.group(1)
101
114
 
102
115
  return interfaces
116
+
117
+
118
+ def check_ping_from_linux(ip_address: str, number_of_ping: int = 4) -> bool:
119
+ try:
120
+ if os.system(f"ping -c {number_of_ping} {ip_address}") == 0:
121
+ return True
122
+ return False
123
+ except Exception as e:
124
+ logger.exception(f"ping to {ip_address} failed: {e}")
125
+ return False
126
+
127
+
128
+ def check_ping_from_windows(ip_address: str, number_of_ping: int = 4) -> bool:
129
+ try:
130
+ if os.system(f"ping -c {number_of_ping} {ip_address}") == 0:
131
+ return True
132
+ return False
133
+ except Exception as e:
134
+ logger.exception(f"ping to {ip_address} failed: {e}")
135
+ return False
136
+
137
+
138
+ def check_ping_status(platform: Platform, ip_address: str, number_of_ping: int = 4) -> bool:
139
+ """
140
+ Check the ping status of an IP address based on the operating system platform.
141
+ """
142
+ if platform in [Platform.LINUX, Platform.MACOS]:
143
+ return check_ping_from_linux(ip_address, number_of_ping)
144
+ if platform == Platform.WINDOWS:
145
+ return check_ping_from_windows(ip_address, number_of_ping)
146
+ raise ValueError(f"Unsupported platform: {platform}")
@@ -3,18 +3,17 @@ from pathlib import Path
3
3
 
4
4
  def get_project_path_by_name(project_name: str) -> str:
5
5
  current_path = Path(__file__).parent
6
- while current_path != current_path.parent:
7
- if str(current_path).endswith(f'/{project_name}'):
6
+ while current_path != current_path.parent: # pylint: disable=W0149
7
+ if str(current_path).endswith(f"/{project_name}"):
8
8
  return str(current_path)
9
9
  current_path = current_path.parent
10
10
  raise FileNotFoundError(
11
- f'Project "{project_name}" not found in any parent directories.\n'
12
- f'Current path: {Path(__file__)}',
11
+ f'Project "{project_name}" not found in any parent directories.\n' f"Current path: {Path(__file__)}",
13
12
  )
14
13
 
15
14
 
16
15
  def get_project_path_by_file(markers: set = None) -> Path:
17
- markers = markers or {'.git', '.gitignore', 'setup.py', 'pyproject.toml', 'LICENSE', 'README.md'}
16
+ markers = markers or {".git", ".gitignore", "setup.py", "pyproject.toml", "LICENSE", "README.md"}
18
17
  for marker in markers:
19
18
  path = Path(__file__).resolve()
20
19
  for parent in path.parents:
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import logging
3
- from typing import Any, Callable
3
+ from collections.abc import Callable
4
+ from typing import Any
4
5
 
5
6
  from custom_python_logger import get_logger
6
7
 
@@ -8,11 +9,7 @@ logger = get_logger(__name__)
8
9
 
9
10
 
10
11
  def log_in_format(
11
- data: Any,
12
- log_level: int = logging.INFO,
13
- indent: int = 4,
14
- sort_keys: bool = True,
15
- default: Callable = None
12
+ data: Any, log_level: int = logging.INFO, indent: int = 4, sort_keys: bool = True, default: Callable = None
16
13
  ) -> None:
17
14
  formatted_data = json.dumps(data, indent=indent, sort_keys=sort_keys, default=default)
18
15
 
@@ -1,8 +1,8 @@
1
- import logging
2
1
  import shutil
3
2
  from pathlib import Path
4
3
 
5
4
  from custom_python_logger.logger import get_logger
5
+
6
6
  from python_base_toolkit.utils.path_utils import get_project_path_by_file
7
7
 
8
8
  logger = get_logger(__name__)
@@ -10,9 +10,9 @@ logger = get_logger(__name__)
10
10
 
11
11
  def delete_pycache_folder(root_dir: Path = None, ignored_dirs: set = None) -> None:
12
12
  root_dir = Path(root_dir) if root_dir else get_project_path_by_file()
13
- ignored_dirs = ignored_dirs or {'.venv'}
13
+ ignored_dirs = ignored_dirs or {".venv"}
14
14
 
15
- for path in root_dir.rglob('__pycache__'):
15
+ for path in root_dir.rglob("__pycache__"):
16
16
  if any(ignored in path.parts for ignored in ignored_dirs):
17
17
  continue
18
18
 
@@ -10,7 +10,7 @@ def generate_random_string(length: int = 8, charset: str = ascii_letters + digit
10
10
  :param charset: The set of characters to use for generating the string
11
11
  Return - A random string based on the specified character set
12
12
  """
13
- return ''.join(choice(charset) for _ in range(length))
13
+ return "".join(choice(charset) for _ in range(length))
14
14
 
15
15
 
16
16
  def generate_random_password(length: int = 8) -> str:
@@ -25,14 +25,14 @@ def generate_random_password(length: int = 8) -> str:
25
25
  password += choice(ascii_lowercase)
26
26
 
27
27
  # Fill the remaining characters with a mix of all types
28
- remaining_chars = ''.join(
28
+ remaining_chars = "".join(
29
29
  choice(ascii_letters + digits + special_characters) for _ in range(length - len(password))
30
30
  )
31
31
 
32
32
  password += remaining_chars
33
33
 
34
34
  # Shuffle the password to make it more random but keep the first character as a letter
35
- return password[0] + ''.join(random.sample(password[1:], len(password) - 1))
35
+ return password[0] + "".join(random.sample(password[1:], len(password) - 1))
36
36
 
37
37
 
38
38
  def generate_random_ipv4() -> str:
@@ -43,9 +43,9 @@ def generate_random_ipv4() -> str:
43
43
 
44
44
 
45
45
  def generate_random_ipv6() -> str:
46
- first_group = f'{random.randint(0x2000, 0x3fff):04x}'
47
- other_groups = [f'{random.randint(0, 0xffff):04x}' for _ in range(7)]
48
- return ':'.join([first_group] + other_groups)
46
+ first_group = f"{random.randint(0x2000, 0x3fff):04x}"
47
+ other_groups = [f"{random.randint(0, 0xffff):04x}" for _ in range(7)]
48
+ return ":".join([first_group] + other_groups)
49
49
 
50
50
 
51
51
  def generate_random_ip(ip_version: int) -> str:
@@ -64,4 +64,4 @@ def generate_random_ip(ip_version: int) -> str:
64
64
  def create_random_text(min_length: int = 64, max_length: int = 4096) -> str:
65
65
  """Generate a random string with a length between min_length and max_length characters."""
66
66
  length = random.randint(min_length, max_length)
67
- return ''.join(random.choice(ascii_letters) for _ in range(length))
67
+ return "".join(random.choice(ascii_letters) for _ in range(length))
@@ -1,10 +1,10 @@
1
- import sys
2
1
  import os
2
+ import sys
3
3
 
4
4
 
5
5
  def get_venv_details() -> dict:
6
6
  return {
7
- 'python_executable_path': sys.executable,
8
- 'python_version': sys.version,
9
- 'venv_path': os.getenv('VIRTUAL_ENV'),
7
+ "python_executable_path": sys.executable,
8
+ "python_version": sys.version,
9
+ "venv_path": os.getenv("VIRTUAL_ENV"),
10
10
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-base-toolkit
3
- Version: 0.0.1
3
+ Version: 0.0.2
4
4
  Summary: A Python package for managing pytest plugins.
5
5
  Home-page: https://github.com/aviz92/python-base-toolkit
6
6
  Author: Avi Zaguri
@@ -13,6 +13,8 @@ Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: setuptools
15
15
  Requires-Dist: wheel
16
+ Requires-Dist: python-dotenv
17
+ Requires-Dist: pre-commit
16
18
  Requires-Dist: colorlog
17
19
  Requires-Dist: pathlib
18
20
  Requires-Dist: requests
@@ -47,15 +49,15 @@ pip install python-toolkit
47
49
  ---
48
50
 
49
51
  ## 🚀 Features
50
- - Constants Pack
51
- - binary
52
+ - Constants Pack
53
+ - binary
52
54
  - time
53
55
 
54
56
  - Decorators Pack
55
57
  - telemetry
56
58
  - timer
57
59
 
58
- - Instances Pack
60
+ - Instances Pack
59
61
  - instance_manager
60
62
 
61
63
  - Utilities Pack
@@ -0,0 +1,30 @@
1
+ python_base_toolkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ python_base_toolkit/consts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ python_base_toolkit/consts/operating_system.py,sha256=8cnaHVz80AecTDhQjhU-i-s88bf1UZ-u0ouxHXxDsmA,80
4
+ python_base_toolkit/consts/units/__init__.py,sha256=1sTK8_l5mO1Osk5dD9aWkyPVXrvYjRJU1brnCmpLdRk,157
5
+ python_base_toolkit/consts/units/binary_units.py,sha256=fgRAP6HXIis6OX4uK8woD-OVD7HtBOBDuhDxJ6AGZVE,412
6
+ python_base_toolkit/consts/units/time_units.py,sha256=aDwRnRR_mbOn2B7NUB9b2-qO98CLFzNE8-ZKfwUZ09Q,216
7
+ python_base_toolkit/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ python_base_toolkit/decorators/telemetry.py,sha256=XKQTYbTqt_3mLVyin5HY7ucgAyAs_hRX_qRd-d7zRJ4,1416
9
+ python_base_toolkit/decorators/timer.py,sha256=MjfkM_aZ1gYG1mmG3Cos3sCM1QdWVyT2wEOEdFA-Uqs,1011
10
+ python_base_toolkit/instances/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ python_base_toolkit/instances/instance_manager.py,sha256=iq72kcPlbc7-AQTuKcBOeqKZbC8vYcsU5GiFXvt5UMs,2278
12
+ python_base_toolkit/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ python_base_toolkit/utils/data_serialization.py,sha256=Xf_JTMQPAQfCDM4b0CJxHK7CjmbmVassYViDa65B97A,1197
14
+ python_base_toolkit/utils/date_time.py,sha256=U1P_8qPnEQzI4DguHVEofYLzlyuWfK7L6VsOKPbMa7c,429
15
+ python_base_toolkit/utils/execute.py,sha256=6QYQWd1Z15Ofb4gcAtXCx90l1D-REwTWDZNybU6OibM,1560
16
+ python_base_toolkit/utils/file_utils.py,sha256=XGiFocSNpb77GeX_hEuR_7juNsSwA-RikpH1CvEG4TM,8793
17
+ python_base_toolkit/utils/generate_id.py,sha256=cXyt7AbHRvKvPsKzVE-zFZ3fPIcJ-VVhCaUh63yYUOA,817
18
+ python_base_toolkit/utils/logo.py,sha256=GXCSyPR7RXNshTuMUq1pqZGVZUSJfaktCOv8dWLSz5Q,140
19
+ python_base_toolkit/utils/network.py,sha256=9Y3appWnaIvliA8Jit6vM0uZOmwf6sDVRwzp6BIouHw,4922
20
+ python_base_toolkit/utils/path_utils.py,sha256=zmyIs-bm5GSP6AH8D-ExCQ91aIc-GKwwjfSNzWgpICE,895
21
+ python_base_toolkit/utils/pretty_print.py,sha256=tj1b6zYSsTLBRFfRMXVx3sYv09T5PvslXV8dpBAeq7g,555
22
+ python_base_toolkit/utils/pycache.py,sha256=X-pWRjAd2xcBtMkcyCuKz34SbHWc2leBHBIjqOVoXmw,911
23
+ python_base_toolkit/utils/random_utils.py,sha256=gTH6k1MKKGNZvBTLc5H-eSmtEGvXEdLqtzXN9aHuu-A,2730
24
+ python_base_toolkit/utils/shorten_url.py,sha256=zsyW3wloFJdVb9s3fhR-olL6ekT03FDlFm2xbFY4viw,359
25
+ python_base_toolkit/utils/venv_details.py,sha256=d1WlZr1LuWz2SXdFP0Hqh6VHXXXSIuXB0oTmWXJrGqM,210
26
+ python_base_toolkit-0.0.2.dist-info/licenses/LICENSE,sha256=cSikHY6SZFsPZSBizCDAJ0-Bjjzxt-JtX6TVbKxwimo,1067
27
+ python_base_toolkit-0.0.2.dist-info/METADATA,sha256=Wo5JsmwNIpe9y3IVV2o-L7RqmfkTC-GY82uD1fXGi0g,2208
28
+ python_base_toolkit-0.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
+ python_base_toolkit-0.0.2.dist-info/top_level.txt,sha256=I9kK6FGKq_6z3aGySoWamY68GRgg0xsL6sS-uyaxJ2k,20
30
+ python_base_toolkit-0.0.2.dist-info/RECORD,,
@@ -1,28 +0,0 @@
1
- python_base_toolkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- python_base_toolkit/consts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- python_base_toolkit/consts/units/__init__.py,sha256=-1lY3rI3SU7gZKlAKl9E6FjputEdKMGxO0K1GJRXSN0,157
4
- python_base_toolkit/consts/units/binary_units.py,sha256=8NssiyGO_cJ-FNAh4EYzVlCKRM5n4Q0GC8sL96kvNl4,420
5
- python_base_toolkit/consts/units/time_units.py,sha256=aDwRnRR_mbOn2B7NUB9b2-qO98CLFzNE8-ZKfwUZ09Q,216
6
- python_base_toolkit/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- python_base_toolkit/decorators/telemetry.py,sha256=bxittYChUb0zRnDoX_miCZKFQukZ1rPjjPmYfXfcQzA,1400
8
- python_base_toolkit/decorators/timer.py,sha256=DU0JoqY5cN5hmLVDrNxaMgkPbYNvN3DGU3-FpZXtJK0,813
9
- python_base_toolkit/instances/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- python_base_toolkit/instances/instance_manager.py,sha256=NDNKVBaYSXvbASehM0YHBWCaYOSLWFJfuKZ7cf0iTho,2058
11
- python_base_toolkit/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- python_base_toolkit/utils/data_serialization.py,sha256=MCF9pALQU2s5tufWXTzW1Dwj3NS1cjI1Le_BL4717iI,1197
13
- python_base_toolkit/utils/date_time.py,sha256=ycWWTPnkLukENza4NzCX8vQ113UGu4ugPJHGyx4Dgx0,429
14
- python_base_toolkit/utils/execute.py,sha256=eppuC5YywOHDK-AwFSmcT5YpuO119fFgpJjcSQY80ks,1535
15
- python_base_toolkit/utils/file_utils.py,sha256=Na6Y1O8PAb21w0y-VnhBFWonOpXl40IrXnefBY8oKNk,8611
16
- python_base_toolkit/utils/logo.py,sha256=X4u0CmBgTJWqn3b_V0MG2mKV1Gw4rLGOLSQmY7hatIs,140
17
- python_base_toolkit/utils/network.py,sha256=i3RyWTJGHt77b45gYn0eO9zqXUkScYZvnq-hOFY_eAk,3585
18
- python_base_toolkit/utils/path_utils.py,sha256=xY0pMHIO-HoWLgc4In-WK8HjsfIwqwozDYzV_nxC_Ps,878
19
- python_base_toolkit/utils/pretty_print.py,sha256=66XQQKUDjTJcClqWIU_eNmKLKz0h7_1hxMItEAsxbyo,544
20
- python_base_toolkit/utils/pycache.py,sha256=YwYGYiERSYQJWg1gYDQH1JmjpZpRYWSdacWd8n6zHD8,925
21
- python_base_toolkit/utils/random_utils.py,sha256=g3yXqei1bGEGxPnAXsdnVtG2DXIF0t68clqul14cAN8,2730
22
- python_base_toolkit/utils/shorten_url.py,sha256=zsyW3wloFJdVb9s3fhR-olL6ekT03FDlFm2xbFY4viw,359
23
- python_base_toolkit/utils/venv_details.py,sha256=B67fyXSXdkLnU-fc7QJgSCSpJX5Sv6D13K7to_CDmf4,210
24
- python_base_toolkit-0.0.1.dist-info/licenses/LICENSE,sha256=cSikHY6SZFsPZSBizCDAJ0-Bjjzxt-JtX6TVbKxwimo,1067
25
- python_base_toolkit-0.0.1.dist-info/METADATA,sha256=8-kOqa9CkOUB3kopAtR8ZX0wqL0MN35Pi-Emuvx_tnk,2156
26
- python_base_toolkit-0.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- python_base_toolkit-0.0.1.dist-info/top_level.txt,sha256=I9kK6FGKq_6z3aGySoWamY68GRgg0xsL6sS-uyaxJ2k,20
28
- python_base_toolkit-0.0.1.dist-info/RECORD,,