osbot-utils 1.17.0__py3-none-any.whl → 1.20.0__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.
Files changed (52) hide show
  1. osbot_utils/base_classes/Kwargs_To_Self.py +3 -54
  2. osbot_utils/base_classes/Type_Safe.py +6 -0
  3. osbot_utils/context_managers/disable_root_loggers.py +30 -0
  4. osbot_utils/helpers/CFormat.py +147 -0
  5. osbot_utils/helpers/CPrint.py +5 -50
  6. osbot_utils/helpers/Print_Table.py +1 -1
  7. osbot_utils/helpers/cache_requests/Cache__Requests__Actions.py +23 -0
  8. osbot_utils/helpers/cache_requests/Cache__Requests__Config.py +32 -0
  9. osbot_utils/helpers/cache_requests/Cache__Requests__Data.py +105 -0
  10. osbot_utils/helpers/cache_requests/Cache__Requests__Invoke.py +55 -0
  11. osbot_utils/helpers/cache_requests/Cache__Requests__Row.py +64 -0
  12. osbot_utils/helpers/cache_requests/Cache__Requests__Table.py +16 -0
  13. osbot_utils/helpers/cache_requests/__init__.py +0 -0
  14. osbot_utils/helpers/cache_requests/flows/flow__Cache__Requests.py +11 -0
  15. osbot_utils/helpers/flows/Flow.py +145 -0
  16. osbot_utils/helpers/flows/Task.py +18 -0
  17. osbot_utils/helpers/flows/__init__.py +0 -0
  18. osbot_utils/helpers/sqlite/{domains/schemas → cache}/Schema__Table__Requests.py +6 -4
  19. osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests.py +104 -0
  20. osbot_utils/helpers/sqlite/{domains → cache}/Sqlite__Cache__Requests__Patch.py +10 -8
  21. osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Sqlite.py +18 -0
  22. osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Table.py +48 -0
  23. osbot_utils/helpers/sqlite/{domains → cache}/Sqlite__DB__Requests.py +8 -7
  24. osbot_utils/helpers/sqlite/cache/TestCase__Sqlite__Cache__Requests.py +35 -0
  25. osbot_utils/helpers/sqlite/cache/__init__.py +0 -0
  26. osbot_utils/helpers/sqlite/domains/Sqlite__DB__Local.py +6 -2
  27. osbot_utils/helpers/{SCP.py → ssh/SCP.py} +23 -20
  28. osbot_utils/helpers/ssh/SSH.py +30 -0
  29. osbot_utils/helpers/ssh/SSH__Cache__Requests.py +66 -0
  30. osbot_utils/helpers/ssh/SSH__Execute.py +158 -0
  31. osbot_utils/helpers/ssh/SSH__Health_Check.py +49 -0
  32. osbot_utils/helpers/ssh/SSH__Linux.py +106 -0
  33. osbot_utils/helpers/ssh/SSH__Python.py +48 -0
  34. osbot_utils/helpers/ssh/TestCase__SSH.py +50 -0
  35. osbot_utils/helpers/ssh/__init__.py +0 -0
  36. osbot_utils/helpers/trace/Trace_Call__Print_Lines.py +1 -1
  37. osbot_utils/testing/Logging.py +15 -5
  38. osbot_utils/testing/Pytest.py +18 -0
  39. osbot_utils/utils/Env.py +27 -9
  40. osbot_utils/utils/Json.py +2 -9
  41. osbot_utils/utils/Misc.py +16 -18
  42. osbot_utils/utils/Objects.py +17 -7
  43. osbot_utils/utils/Python_Logger.py +54 -38
  44. osbot_utils/utils/Str.py +20 -3
  45. osbot_utils/utils/Toml.py +33 -0
  46. osbot_utils/version +1 -1
  47. {osbot_utils-1.17.0.dist-info → osbot_utils-1.20.0.dist-info}/METADATA +2 -2
  48. {osbot_utils-1.17.0.dist-info → osbot_utils-1.20.0.dist-info}/RECORD +50 -23
  49. osbot_utils/helpers/SSH.py +0 -172
  50. osbot_utils/helpers/sqlite/domains/Sqlite__Cache__Requests.py +0 -214
  51. {osbot_utils-1.17.0.dist-info → osbot_utils-1.20.0.dist-info}/LICENSE +0 -0
  52. {osbot_utils-1.17.0.dist-info → osbot_utils-1.20.0.dist-info}/WHEEL +0 -0
osbot_utils/utils/Misc.py CHANGED
@@ -10,11 +10,11 @@ import textwrap
10
10
  import re
11
11
  import uuid
12
12
  import warnings
13
- from datetime import datetime, timedelta
14
- from secrets import token_bytes
15
- from time import sleep
16
- from typing import Iterable
17
- from urllib.parse import quote_plus, unquote_plus
13
+ from datetime import datetime, timedelta
14
+ from secrets import token_bytes
15
+ from time import sleep
16
+ from typing import Iterable
17
+ from urllib.parse import quote_plus, unquote_plus
18
18
 
19
19
 
20
20
  if sys.version_info >= (3, 11):
@@ -23,11 +23,6 @@ else:
23
23
  from datetime import timezone # For versions before 3.11, we need to use a different method or library to handle UTC
24
24
  UTC = timezone.utc
25
25
 
26
- def ansi_text_visible_length(text):
27
- ansi_escape = re.compile(r'\x1b\[[0-9;]*m') # This regex matches the escape sequences used for text formatting
28
- visible_text = ansi_escape.sub('', text) # Remove the escape sequences
29
- return len(visible_text) # Return the length of the remaining text
30
-
31
26
  def append_random_string(target, length=6, prefix='-'):
32
27
  return f'{target}{random_string(length, prefix)}'
33
28
 
@@ -125,7 +120,7 @@ def date_to_str(date, date_format='%Y-%m-%d'):
125
120
  return date.strftime(date_format)
126
121
 
127
122
  #note: this is here at the moment due to a circular dependency with lists and objects
128
- def list_set(target):
123
+ def list_set(target: object) -> object:
129
124
  if hasattr(target, '__iter__'):
130
125
  return sorted(list(set(target)))
131
126
  return []
@@ -148,8 +143,6 @@ def get_random_color(max=5):
148
143
  colors = ['skyblue', 'darkseagreen', 'palevioletred', 'coral', 'darkgray']
149
144
  return colors[random_number(0, max-1)]
150
145
 
151
- def in_github_action():
152
- return os.getenv('GITHUB_ACTIONS') == 'true'
153
146
 
154
147
  def is_debugging():
155
148
  return sys.gettrace() is not None
@@ -238,8 +231,6 @@ def lower(target : str):
238
231
  return target.lower()
239
232
  return ""
240
233
 
241
- def not_in_github_action():
242
- return in_github_action() is False
243
234
 
244
235
  def size(target=None):
245
236
  if target and hasattr(target, '__len__'):
@@ -264,17 +255,17 @@ def print_time_now(use_utc=True):
264
255
  print(time_now(use_utc=use_utc))
265
256
 
266
257
  def str_sha256(text: str):
267
- if text:
258
+ if type(text) is str:
268
259
  return bytes_sha256(text.encode())
269
260
  return None
270
261
 
271
262
  def str_sha384(text:str):
272
- if text:
263
+ if type(text) is str:
273
264
  return bytes_sha384(text.encode())
274
265
  return
275
266
 
276
267
  def str_sha384_as_base64(text:str, include_prefix=True):
277
- if text:
268
+ if type(text) is str:
278
269
  hash_object = hashlib.sha384(text.encode())
279
270
  digest = hash_object.digest() # Getting the digest of the hash
280
271
  digest_base64 = base64.b64encode(digest).decode() # Converting the digest to Base64 encoding
@@ -424,6 +415,11 @@ def str_to_base64(target):
424
415
  def str_to_bytes(target):
425
416
  return target.encode()
426
417
 
418
+ def str_to_bool(value):
419
+ if type(value) is str:
420
+ return value.lower() in ('true', '1', 'yes')
421
+ return False
422
+
427
423
  def str_to_date(str_date, format='%Y-%m-%d %H:%M:%S.%f'):
428
424
  return datetime.strptime(str_date,format)
429
425
 
@@ -490,9 +486,11 @@ date_time_from_timestamp = timestamp_to_datetime
490
486
  date_time_from_time_stamp = timestamp_to_datetime
491
487
  date_time_utc_now = utc_now
492
488
 
489
+ hash_sha256 = str_sha256
493
490
 
494
491
  new_guid = random_uuid
495
492
 
493
+ sha_256 = str_sha256
496
494
  str_lines = split_lines
497
495
  str_remove = remove
498
496
 
@@ -1,8 +1,5 @@
1
1
  # todo add tests
2
2
  import inspect
3
- import io
4
- import json
5
- import os
6
3
  import pickle
7
4
  import sys
8
5
  import types
@@ -38,7 +35,15 @@ def are_types_compatible_for_assigment(source_type, target_type):
38
35
  return True
39
36
  if target_type in source_type.__mro__: # this means that the source_type has the target_type has of its base types
40
37
  return True
41
-
38
+ if target_type is callable: # handle case where callable was used as the target type
39
+ if source_type is types.MethodType: # and a method or function was used as the source type
40
+ return True
41
+ if source_type is types.FunctionType:
42
+ return True
43
+ if source_type is staticmethod:
44
+ return True
45
+ if target_type is typing.Any:
46
+ return True
42
47
  return False
43
48
 
44
49
  def are_types_magic_mock(source_type, target_type):
@@ -303,7 +308,10 @@ def pickle_save_to_bytes(target: object) -> bytes:
303
308
 
304
309
  def pickle_load_from_bytes(pickled_data: bytes):
305
310
  if type(pickled_data) is bytes:
306
- return pickle.loads(pickled_data)
311
+ try:
312
+ return pickle.loads(pickled_data)
313
+ except Exception:
314
+ return {}
307
315
 
308
316
  def value_type_matches_obj_annotation_for_attr(target, attr_name, value):
309
317
  if hasattr(target, '__annotations__'):
@@ -329,14 +337,16 @@ def value_type_matches_obj_annotation_for_attr(target, attr_name, value):
329
337
 
330
338
  # helper duplicate methods
331
339
  base_types = base_classes
340
+ bytes_to_obj = pickle_load_from_bytes
332
341
 
333
342
  full_type_name = class_full_name
334
343
 
335
344
  obj_list_set = obj_keys
336
345
  obj_info = print_object_members
337
346
  obj_methods = print_object_methods
338
-
339
347
  obj_to_bytes = pickle_save_to_bytes
340
- bytes_to_obj = pickle_load_from_bytes
348
+
349
+ pickle_from_bytes = pickle_load_from_bytes
350
+ pickle_to_bytes = pickle_save_to_bytes
341
351
 
342
352
  type_full_name = class_full_name
@@ -2,19 +2,21 @@ import inspect
2
2
  import logging
3
3
  import sys
4
4
  import types
5
- from logging import Logger, StreamHandler, FileHandler
6
- from logging.handlers import MemoryHandler
7
-
8
- from osbot_utils.decorators.lists.group_by import group_by
9
- from osbot_utils.decorators.lists.index_by import index_by
10
- from osbot_utils.decorators.methods.cache_on_function import cache_on_function
11
- from osbot_utils.decorators.methods.cache_on_self import cache_on_self
12
- from osbot_utils.utils.Misc import random_string
13
- from osbot_utils.utils.Files import temp_file
14
- from osbot_utils.utils.Objects import obj_dict
5
+ from logging import Logger, StreamHandler, FileHandler
6
+ from logging.handlers import MemoryHandler
7
+ from osbot_utils.base_classes.Type_Safe import Type_Safe
8
+ from osbot_utils.decorators.lists.group_by import group_by
9
+ from osbot_utils.decorators.lists.index_by import index_by
10
+ from osbot_utils.decorators.methods.cache_on_function import cache_on_function
11
+ from osbot_utils.utils.Misc import random_string
12
+ from osbot_utils.utils.Files import temp_file
13
+ from osbot_utils.utils.Objects import obj_dict
14
+
15
+ #DEFAULT_LOG_FORMAT = '%(asctime)s.%(msecs)03d %(levelname)s - %(message)s'
15
16
 
16
17
  DEFAULT_LOG_LEVEL = logging.DEBUG
17
18
  DEFAULT_LOG_FORMAT = '%(asctime)s\t|\t%(name)s\t|\t%(levelname)s\t|\t%(message)s'
19
+ DEFAULT_LOG_DATE_FORMAT = '%M:%S'
18
20
  MEMORY_LOGGER_CAPACITY = 1024*10
19
21
  MEMORY_LOGGER_FLUSH_LEVEL = logging.ERROR
20
22
 
@@ -29,10 +31,10 @@ MEMORY_LOGGER_FLUSH_LEVEL = logging.ERROR
29
31
  class Python_Logger_Config:
30
32
 
31
33
  def __init__(self):
32
- self.elastic_host = None
33
- self.elastic_password = None
34
- self.elastic_port = None
35
- self.elastic_username = None
34
+ # self.elastic_host = None # this needs to be implemented in OSBot_Elastic
35
+ # self.elastic_password = None
36
+ # self.elastic_port = None
37
+ # self.elastic_username = None
36
38
  #self.log_to_aws_s3 = False # todo
37
39
  #self.log_to_aws_cloud_trail = False # todo
38
40
  #self.log_to_aws_firehose = False # todo
@@ -42,26 +44,27 @@ class Python_Logger_Config:
42
44
  self.log_to_memory = False
43
45
  self.path_logs = None
44
46
  self.log_format = DEFAULT_LOG_FORMAT
47
+ self.log_date_format = DEFAULT_LOG_DATE_FORMAT
45
48
  self.log_level = DEFAULT_LOG_LEVEL
46
49
 
47
50
 
48
- class Python_Logger:
51
+ class Python_Logger(Type_Safe):
49
52
  config : Python_Logger_Config
50
53
  logger : Logger
51
54
  logger_name : str
52
- critical : types.FunctionType # these will be replaced by Python_Logger_Config.setup_log_methods
53
- debug : types.FunctionType
54
- error : types.FunctionType
55
- exception : types.FunctionType
56
- info : types.FunctionType
57
- ok : types.FunctionType
58
- warning : types.FunctionType
59
-
60
- def __init__(self, logger_name= None, logger_config : Python_Logger_Config = None):
61
- self.set_logger_name(logger_name)
62
- #self.logger_name = logger_name or random_string(prefix="Python_Logger_")
63
- self.set_config(logger_config)
64
- # self.logger = None
55
+
56
+ critical : types.MethodType # these will be replaced by Python_Logger_Config.setup_log_methods
57
+ debug : types.MethodType
58
+ error : types.MethodType
59
+ exception : types.MethodType
60
+ info : types.MethodType
61
+ ok : types.MethodType
62
+ warning : types.MethodType
63
+
64
+ def __init__(self, **kwargs):
65
+ super().__init__(**kwargs)
66
+ self.set_logger_name(self.logger_name)
67
+ self.set_config (self.config )
65
68
  self.setup() # todo: understand side effect of setting up logger on __init__
66
69
 
67
70
  def disable(self):
@@ -134,9 +137,11 @@ class Python_Logger:
134
137
  self.config = Python_Logger_Config()
135
138
  return self.config
136
139
 
137
- def set_log_format(self, log_format):
140
+ def set_log_format(self, log_format=None, date_format=None):
138
141
  if log_format:
139
142
  self.config.log_format = log_format
143
+ if date_format:
144
+ self.config.log_date_format = date_format
140
145
 
141
146
  def set_log_level(self, level=None):
142
147
  level = level or self.config.log_level
@@ -159,7 +164,7 @@ class Python_Logger:
159
164
  def log_handler_file(self):
160
165
  return self.log_handler(logging.FileHandler)
161
166
 
162
- def log_handler_memory(self):
167
+ def log_handler_memory(self): # todo: change how this memory logger works (see notes in the other memory logger methods in Python_Logger
163
168
  return self.log_handler(MemoryHandler)
164
169
 
165
170
  def log_handlers(self):
@@ -178,7 +183,7 @@ class Python_Logger:
178
183
  return self.log_handlers_remove(handler)
179
184
 
180
185
  def log_formatter(self):
181
- return logging.Formatter(self.config.log_format)
186
+ return logging.Formatter(fmt=self.config.log_format, datefmt=self.config.log_date_format)
182
187
 
183
188
  def log_level(self):
184
189
  return self.config.log_level
@@ -189,7 +194,7 @@ class Python_Logger:
189
194
  self.config.log_to_console = True
190
195
  return self.add_handler_console()
191
196
 
192
- def add_memory_logger(self):
197
+ def add_memory_logger(self): # todo: figure out the exact workflow of this, since this memory logger is not tied to the current instance of Python_Logger (it's a global logger)
193
198
  self.config.log_to_memory = True
194
199
  return self.add_handler_memory()
195
200
 
@@ -197,7 +202,7 @@ class Python_Logger:
197
202
  self.config.log_to_file = True
198
203
  return self.add_handler_file(path_log_file=path_log_file)
199
204
 
200
- def remove_memory_logger(self):
205
+ def remove_memory_logger(self): # todo: improve this workflow since this operating at the global loggers level, which means that this will get the first one, not the one from this python_Logger
201
206
  memory_logger = self.log_handler_memory()
202
207
  if self.log_handlers_remove(memory_logger):
203
208
  self.config.log_to_file = False
@@ -235,16 +240,18 @@ class Python_Logger:
235
240
  memory_handler = MemoryHandler(capacity=capacity, flushLevel=flush_level, target=target,flushOnClose=True)
236
241
  memory_handler.setLevel(self.log_level())
237
242
  self.logger.addHandler(memory_handler)
238
- return True
239
- return False
243
+ return memory_handler
240
244
 
241
245
  # Utils
246
+
242
247
  def memory_handler(self) -> MemoryHandler:
243
248
  return self.log_handler_memory()
244
249
 
245
250
  def memory_handler_buffer(self):
246
251
  if self.config.log_to_memory:
247
- return self.memory_handler().buffer
252
+ memory_handler = self.memory_handler()
253
+ if memory_handler:
254
+ return memory_handler.buffer
248
255
  return []
249
256
 
250
257
  def memory_handler_clear(self):
@@ -253,6 +260,7 @@ class Python_Logger:
253
260
  memory_handler.buffer = []
254
261
  return True
255
262
  return False
263
+
256
264
  def memory_handler_exceptions(self):
257
265
  return self.memory_handler_logs(index_by='levelname').get('EXCEPTIONS', {})
258
266
 
@@ -272,8 +280,16 @@ class Python_Logger:
272
280
  return {}
273
281
 
274
282
  def memory_handler_messages(self):
275
- return [log_entry.get('message') for log_entry in self.memory_handler_logs()]
276
-
283
+ messages = []
284
+ for log_entry in self.memory_handler_logs():
285
+ message = log_entry.get('message') or log_entry.get('msg') or '(log message not found in log entry)' # todo: figure out the scenarios that lead to a value in 'msg' or in 'message'
286
+ messages.append(message)
287
+ return messages
288
+
289
+ # Root logger
290
+ def root_logger__clear_handlers(self): # useful in some debugging sessinon
291
+ logging.root.handlers.clear()
292
+ return self
277
293
  # Logging methods
278
294
 
279
295
  # def debug (self, msg='', *args, **kwargs): return self._log('debug' , msg, *args, **kwargs)
osbot_utils/utils/Str.py CHANGED
@@ -1,10 +1,27 @@
1
+ import re
1
2
  import textwrap
2
- from html import escape, unescape
3
-
4
- from osbot_utils.utils.Files import safe_file_name
3
+ from html import escape, unescape
4
+ from osbot_utils.utils.Files import safe_file_name
5
5
 
6
6
  # todo: refactor this this class all str related methods (mainly from the Misc class)
7
7
 
8
+ ANSI_ESCAPE_PATTERN = re.compile(r'\x1b\[[0-9;]*m')
9
+
10
+ def ansi_text_visible_length(ansi_text):
11
+ if type(ansi_text) is str:
12
+ ansi_escape = re.compile(ANSI_ESCAPE_PATTERN) # This regex matches the escape sequences used for text formatting
13
+ visible_text = ansi_escape.sub('', ansi_text) # Remove the escape sequences
14
+ return len(visible_text) # Return the length of the remaining text
15
+
16
+ def ansi_to_text(ansi_text: str):
17
+ if type(ansi_text) is str:
18
+ return ANSI_ESCAPE_PATTERN.sub('', ansi_text)
19
+
20
+ def ansis_to_texts(ansis_texts: list): # todo: find a better name for this method :)
21
+ if type(ansis_texts) is list:
22
+ return [ansi_to_text(ansi_text) for ansi_text in ansis_texts]
23
+ return []
24
+
8
25
  def html_escape(value: str):
9
26
  return escape(value)
10
27
 
@@ -0,0 +1,33 @@
1
+ import sys
2
+
3
+ if sys.version_info >= (3, 11):
4
+ import tomllib
5
+ else:
6
+ tomllib = None
7
+
8
+ def dict_to_toml(data, indent_level=0):
9
+ toml_str = ""
10
+ indent = " " * (indent_level * 4)
11
+
12
+ for key, value in data.items():
13
+ if isinstance(value, dict):
14
+ toml_str += f"{indent}[{key}]\n"
15
+ toml_str += dict_to_toml(value, indent_level + 1)
16
+ elif isinstance(value, (list, tuple, set)):
17
+ toml_str += f"{indent}{key} = [\n"
18
+ for item in value:
19
+ toml_str += f"{indent} {repr(item)},\n"
20
+ toml_str += f"{indent}]\n"
21
+ elif isinstance(value, str):
22
+ toml_str += f"{indent}{key} = '{value}'\n"
23
+ elif isinstance(value, bool):
24
+ toml_str += f"{indent}{key} = {str(value).lower()}\n"
25
+ else:
26
+ toml_str += f"{indent}{key} = {value}\n"
27
+
28
+ return toml_str
29
+
30
+ def toml_to_dict(toml_string):
31
+ if tomllib is None:
32
+ raise NotImplementedError("TOML parsing is not supported in Python versions earlier than 3.11")
33
+ return tomllib.loads(toml_string)
osbot_utils/version CHANGED
@@ -1 +1 @@
1
- v1.17.0
1
+ v1.20.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: osbot_utils
3
- Version: 1.17.0
3
+ Version: 1.20.0
4
4
  Summary: OWASP Security Bot - Utils
5
5
  Home-page: https://github.com/owasp-sbot/OSBot-Utils
6
6
  License: MIT
@@ -22,7 +22,7 @@ Description-Content-Type: text/markdown
22
22
 
23
23
  Powerful Python util methods and classes that simplify common apis and tasks.
24
24
 
25
- ![Current Release](https://img.shields.io/badge/release-v1.17.0-blue)
25
+ ![Current Release](https://img.shields.io/badge/release-v1.20.0-blue)
26
26
  [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](https://codecov.io/gh/owasp-sbot/OSBot-Utils)
27
27
 
28
28
 
@@ -1,11 +1,13 @@
1
1
  osbot_utils/__init__.py,sha256=DdJDmQc9zbQUlPVyTJOww6Ixrn9n4bD3ami5ItQfzJI,16
2
2
  osbot_utils/base_classes/Cache_Pickle.py,sha256=kPCwrgUbf_dEdxUz7vW1GuvIPwlNXxuRhb-H3AbSpII,5884
3
3
  osbot_utils/base_classes/Kwargs_To_Disk.py,sha256=HHoy05NC_w35WcT-OnSKoSIV_cLqaU9rdjH0_KNTM0E,1096
4
- osbot_utils/base_classes/Kwargs_To_Self.py,sha256=mkfnvlKVpNW1fI8pIIkrpP9w7eA7J6giRSAyW4HXWFY,19864
4
+ osbot_utils/base_classes/Kwargs_To_Self.py,sha256=zahQ344JF13t4UO7xfnaSrcWPTXn052rMsjTFLpDunE,17450
5
+ osbot_utils/base_classes/Type_Safe.py,sha256=PHBIXCRumEnXGognc1qKDJzcAK_vAsylEWfREG5nvjY,260
5
6
  osbot_utils/base_classes/Type_Safe__List.py,sha256=-80C9OhsK6iDR2dAG8yNLAZV0qg5x3faqvSUigFCMJw,517
6
7
  osbot_utils/base_classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
8
  osbot_utils/context_managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
9
  osbot_utils/context_managers/capture_duration.py,sha256=l4l4UKC065Vi-zwyr4Ru_pVALsthCDQSXFR1mCl0DVQ,1187
10
+ osbot_utils/context_managers/disable_root_loggers.py,sha256=XDMbKATcRbmUQSMKaOhk68DANVdhbBvDxj15iXjIkw0,1056
9
11
  osbot_utils/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
12
  osbot_utils/decorators/classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
13
  osbot_utils/decorators/classes/singleton.py,sha256=ZBYw2W4Qmo0mlHQQqDJyScaXO6pmbftru9YBBdUowjY,332
@@ -52,15 +54,14 @@ osbot_utils/graphs/mgraph/MGraph__Random_Graphs.py,sha256=MDCmnrv7QcGXJeZDYc4y5W
52
54
  osbot_utils/graphs/mgraph/MGraph__Serializer.py,sha256=F8epC-55qMyBZiMD5SLPVmLgIKj2iosiblb7heTH_cQ,1408
53
55
  osbot_utils/graphs/mgraph/MGraphs.py,sha256=W8GlTBQ-1nBb9Zj3nbZ3QetyaP1LlkhMBVOiOLIsCE4,636
54
56
  osbot_utils/graphs/mgraph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
- osbot_utils/helpers/CPrint.py,sha256=ciKgiq83_oHTvTo2-04omv8AJrEfSqSWXVWwm0xgyhQ,4105
57
+ osbot_utils/helpers/CFormat.py,sha256=1_XvqGwgU6qC97MbzcKF0o7s9mCXpU5Kq9Yf-1ixUwY,6808
58
+ osbot_utils/helpers/CPrint.py,sha256=ztKPNmT8BGxeyPXSQKRs63PqqbgxKDz_BiZmzFMup9g,1413
56
59
  osbot_utils/helpers/Dict_To_Attr.py,sha256=NdhXl5mJH7-NaBk213amzc5Nfy3tJgW-N_uYIRE4hoc,208
57
60
  osbot_utils/helpers/Local_Cache.py,sha256=nxyorvXbXyWdlKkLeSeWmUhw1gE4SpOdso919IKfIE4,3046
58
61
  osbot_utils/helpers/Local_Caches.py,sha256=HvuP5CURyVm_fVvJX-S4dml2bhRauzgA3be237yTaeY,1814
59
- osbot_utils/helpers/Print_Table.py,sha256=vYpz-HXX_dDIzSRptwkzpOFADT9R7w3FG9skbVqOkbA,19109
62
+ osbot_utils/helpers/Print_Table.py,sha256=LEXbyqGg_6WSraI4cob4bNNSu18ddqvALp1zGK7bPhs,19126
60
63
  osbot_utils/helpers/Python_Audit.py,sha256=shpZlluJwqJBAlad6xN01FkgC1TsQ48RLvR5ZjmrKa4,1539
61
64
  osbot_utils/helpers/Random_Seed.py,sha256=14btja8LDN9cMGWaz4fCNcMRU_eyx49gas-_PQvHgy4,634
62
- osbot_utils/helpers/SCP.py,sha256=fK1xu5mk_axsI7MU2-WIXEjdYetWkUBDb33p6oALgaI,2687
63
- osbot_utils/helpers/SSH.py,sha256=-dQkwGJzMRrq5iWWf0ZdZkrmHiFpSBt0lMkX9iTti0M,7264
64
65
  osbot_utils/helpers/Type_Registry.py,sha256=Ajk3SyMSKDi2g9SJYUtTgg7PZkAgydaHcpbGuEN3S94,311
65
66
  osbot_utils/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
67
  osbot_utils/helpers/ast/Ast.py,sha256=lcPQOSxXI6zgmMnIVF9WM6ISqViWX-sq4d_UC0CDG8s,1155
@@ -139,6 +140,17 @@ osbot_utils/helpers/ast/nodes/Ast_With.py,sha256=MO3doSFTxQEXUm8t4wDG5hFfWa_ByOM
139
140
  osbot_utils/helpers/ast/nodes/Ast_With_Item.py,sha256=ger_t7_sEb2HiHpFwXBRAUJTCgXBfKZyv2uGuHMnQqA,260
140
141
  osbot_utils/helpers/ast/nodes/Ast_Yield.py,sha256=7ATJnOHekV9XquMTYYSJ6xqyDvgwFc596myKPpHLddk,197
141
142
  osbot_utils/helpers/ast/nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
143
+ osbot_utils/helpers/cache_requests/Cache__Requests__Actions.py,sha256=r1CMR4qHO9is66lexJQ-BNUmBWcEjOSTG_qC0xsoorY,1228
144
+ osbot_utils/helpers/cache_requests/Cache__Requests__Config.py,sha256=KxBjj56YTjZjKsO9TLsRfkcHYJPIGDXZ6rFskaNnh-4,935
145
+ osbot_utils/helpers/cache_requests/Cache__Requests__Data.py,sha256=mx9mVGWwuixPxZmwU49Y4fUTfRaPNZosiX2PStaKBic,5284
146
+ osbot_utils/helpers/cache_requests/Cache__Requests__Invoke.py,sha256=8sLJcLvxaHMnvD2gOL3kF3KR1dD2fIJq371SL9WNpRQ,2751
147
+ osbot_utils/helpers/cache_requests/Cache__Requests__Row.py,sha256=h-yc7NkpScbHwwf2km5wwKig-wLi4WuB9P4fVEdFGdM,3182
148
+ osbot_utils/helpers/cache_requests/Cache__Requests__Table.py,sha256=RgxAYhm-FIrXXteQRtD91pOLq8JXhSzxb51Jb6MTUdY,391
149
+ osbot_utils/helpers/cache_requests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
+ osbot_utils/helpers/cache_requests/flows/flow__Cache__Requests.py,sha256=xgx_oExxkcvRwQN1UCobimECIMUKGoIX5oGdCmp8Nyw,243
151
+ osbot_utils/helpers/flows/Flow.py,sha256=3ZqIGPbAzxY_Zzua188LqWeLCnYrtxAs2wUj5rocPec,4929
152
+ osbot_utils/helpers/flows/Task.py,sha256=Kzh_Zb0V5Fj6wo5Xd_kbGqUYNcZ88jUNorCZnaE8e24,491
153
+ osbot_utils/helpers/flows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
142
154
  osbot_utils/helpers/html/Dict_To_Css.py,sha256=u6B4Mx7PXr-gDrTrs1hgknnvsZVK4Fic5LqedKjo-lk,1097
143
155
  osbot_utils/helpers/html/Dict_To_Html.py,sha256=OlRSaDGOeseBNTxRB2ho5whqEacMXeAXWOfeVSEYqC4,3355
144
156
  osbot_utils/helpers/html/Dict_To_Tags.py,sha256=vYG-KPj409ijsWDUHmEY0JvrtH02bwa8hU-P7yZWTFA,3766
@@ -178,15 +190,19 @@ osbot_utils/helpers/sqlite/Sqlite__Table__Create.py,sha256=dkzv-H4WCu2yt9Hx7ANuK
178
190
  osbot_utils/helpers/sqlite/Temp_Sqlite__Database__Disk.py,sha256=-BhK0_3lSJPWDt-QS8IQDfrw2K_drjtn-yXyf9GbER4,520
179
191
  osbot_utils/helpers/sqlite/Temp_Sqlite__Table.py,sha256=Na2dOHlYSVUKK7STHwdzBYbQgvW2a6cEhUnlC0-T8wk,729
180
192
  osbot_utils/helpers/sqlite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
181
- osbot_utils/helpers/sqlite/domains/Sqlite__Cache__Requests.py,sha256=w5HmzkXqikGggS93obZWsqPRp6d2g7Vs74U9WI_u6Vc,10362
182
- osbot_utils/helpers/sqlite/domains/Sqlite__Cache__Requests__Patch.py,sha256=XiqSPnMUP7VIUBy2QZc_ql-pfG2kueTWNsjqt9pdhoY,2322
193
+ osbot_utils/helpers/sqlite/cache/Schema__Table__Requests.py,sha256=fvLyTYYKighMEjZW2gGrKoyKIqDoitrvO0l0nLdDqTs,381
194
+ osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests.py,sha256=v6a1pDzdwIfk-5KQajz1NTNrIozYFxxxIrxDnppsli8,6190
195
+ osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Patch.py,sha256=HB-LbZQ0VHi9cJm0647WJKUZIjesMppKQ3ZbTOsMgCI,2474
196
+ osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Sqlite.py,sha256=HInQAjpmPysVkAcizaZkZe4WD8LENk3zX9h9-3yAJeM,782
197
+ osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Table.py,sha256=77uO-8WLmzBh5A4Y2VVclKlp2kn1aZ6iJVCtOr4zYFo,2830
198
+ osbot_utils/helpers/sqlite/cache/Sqlite__DB__Requests.py,sha256=CWB-hTcgly2T_7HOZM5gUgfdsvgMus5nX2M_wpjVLZs,1643
199
+ osbot_utils/helpers/sqlite/cache/TestCase__Sqlite__Cache__Requests.py,sha256=TLUdQC6vsf5BcDP15CCeoYkipVG30bzqFcqEJpH4dWg,1645
200
+ osbot_utils/helpers/sqlite/cache/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
183
201
  osbot_utils/helpers/sqlite/domains/Sqlite__DB__Files.py,sha256=tirQs4VjnjzGagaT17NigqprMuQiELHm5FwAE5PJT1U,1510
184
202
  osbot_utils/helpers/sqlite/domains/Sqlite__DB__Graph.py,sha256=aGykK4Qll5Rn0xJR4RvF5bN6llNEjx-Vst52XTVSNio,1751
185
203
  osbot_utils/helpers/sqlite/domains/Sqlite__DB__Json.py,sha256=ILx1wOsmwmvV2yb_fMzLzo18uGNub8cxhBrRfYxCCqA,3808
186
- osbot_utils/helpers/sqlite/domains/Sqlite__DB__Local.py,sha256=n5kGCVkVC16JBEBfwh8sXmCJMSAtrkAUtSgXggHXVkc,932
187
- osbot_utils/helpers/sqlite/domains/Sqlite__DB__Requests.py,sha256=8Txl9kX1kHMTEpL-bIjJbzcCfMFb4nHeLrhdIiBtgAc,1541
204
+ osbot_utils/helpers/sqlite/domains/Sqlite__DB__Local.py,sha256=liN_0gyXmQyqnsmiz0RYanSCRI0VoIbwSBf4buM0l-w,1093
188
205
  osbot_utils/helpers/sqlite/domains/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
189
- osbot_utils/helpers/sqlite/domains/schemas/Schema__Table__Requests.py,sha256=dewvm_GZhGT5gfX6pVK55wVF_7mtSik2IUHus6bNS6E,443
190
206
  osbot_utils/helpers/sqlite/domains/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
191
207
  osbot_utils/helpers/sqlite/models/Sqlite__Field__Type.py,sha256=4xsnRLrU13ZT1GisVQZYFn3m7sw6DbY6pg3cg3Ug2cI,1114
192
208
  osbot_utils/helpers/sqlite/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -200,11 +216,20 @@ osbot_utils/helpers/sqlite/tables/Sqlite__Table__Edges.py,sha256=YwlWj9GYBDeotqD
200
216
  osbot_utils/helpers/sqlite/tables/Sqlite__Table__Files.py,sha256=ZlhTqroHd9T8vqNwYpRv5cYHw7Fi-F6fxANh_Fr0nt4,3613
201
217
  osbot_utils/helpers/sqlite/tables/Sqlite__Table__Nodes.py,sha256=GT8h3wD4hGvEtqQuBs0sBbcu2ydktRHTi95PEL2ffHQ,1721
202
218
  osbot_utils/helpers/sqlite/tables/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
219
+ osbot_utils/helpers/ssh/SCP.py,sha256=9PgJbyWKfxJj00Ijaj7o6ffxPXuNoureb6JlHMPbHww,3330
220
+ osbot_utils/helpers/ssh/SSH.py,sha256=El2Op9b_pcr7msolwbbtkW74R2f_BJN_jdf3SQk_gk8,1081
221
+ osbot_utils/helpers/ssh/SSH__Cache__Requests.py,sha256=Dqh4biVcuaXbQVvn3Tx-kSGBGHiF-2wVsgu96EhD6gU,3359
222
+ osbot_utils/helpers/ssh/SSH__Execute.py,sha256=2RjLEf8UuxsYjRoJDmbNdmx5LGgEN4pDS-DhXe3_mDs,6252
223
+ osbot_utils/helpers/ssh/SSH__Health_Check.py,sha256=WDmBD6ejNcBeicXfjpsiNzH-WR3Jejx0re3WfwjSWyQ,2083
224
+ osbot_utils/helpers/ssh/SSH__Linux.py,sha256=O1uyKcklaj2tHqQZln7dVinzjl9-EI52KzP8ojQr244,4330
225
+ osbot_utils/helpers/ssh/SSH__Python.py,sha256=O2DAwkbXzwkis8lffoqIL2NPSfYcN44Mr8i9Ey2iMKk,2066
226
+ osbot_utils/helpers/ssh/TestCase__SSH.py,sha256=rlhkiVr1OR_3uiwqK2dVZ-yBwZZpUhMq6BPT2p21H1s,1598
227
+ osbot_utils/helpers/ssh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
203
228
  osbot_utils/helpers/trace/Trace_Call.py,sha256=xTmR5U2u0vKnIgMSu-4NAibWKIV4-Eql3vACwOr1lkw,6329
204
229
  osbot_utils/helpers/trace/Trace_Call__Config.py,sha256=6nJplzrY1adz3WcwTIuwEhBCk1P0U0NbyWRzDyIox_Q,3250
205
230
  osbot_utils/helpers/trace/Trace_Call__Graph.py,sha256=HCrXRKQI42DIQxxyFLcaosWiOcUyoITbeV17ICdXcXM,1156
206
231
  osbot_utils/helpers/trace/Trace_Call__Handler.py,sha256=Ay5YEmwr8ZCK7YfFWCkOTys5zmiM3qrS0ebwGFx9-hc,11533
207
- osbot_utils/helpers/trace/Trace_Call__Print_Lines.py,sha256=RKsOhhG6Bo8LlgDKg88EfQ39EocYDMzmyJ5wycCnSus,4849
232
+ osbot_utils/helpers/trace/Trace_Call__Print_Lines.py,sha256=cy7zLv0_JNxdOIQPfZk6J9bv6AkIW6O643w0ykClXbw,4820
208
233
  osbot_utils/helpers/trace/Trace_Call__Print_Traces.py,sha256=2LGeWMGP1uhSojGMmJmL3bH2B5LFIlfYEqEPNqoyKJw,8628
209
234
  osbot_utils/helpers/trace/Trace_Call__Stack.py,sha256=pIvZ2yP4tymOQraUR2N5R-qlmg5QijyLxt85zmMajUs,7462
210
235
  osbot_utils/helpers/trace/Trace_Call__Stack_Node.py,sha256=X4Pnlf9ptnRGF4utg8Ooqzx8PyOT3SO7x4qs_osk86Y,1833
@@ -217,9 +242,10 @@ osbot_utils/testing/Duration.py,sha256=iBrczAuw6j3jXtG7ZPraT0PXbCILEcCplJbqei96d
217
242
  osbot_utils/testing/Hook_Method.py,sha256=A1t6WQzeR9hv5ddaz7ILtvKyJpRrRBRnftB-zgcIQpA,4126
218
243
  osbot_utils/testing/Log_To_Queue.py,sha256=pZQ7I1ne-H365a4WLS60oAD-B16pxIZO4suvCdaTW8U,1703
219
244
  osbot_utils/testing/Log_To_String.py,sha256=hkjWsJfV68uqgX9nvVqUN3mVPxZQDb-6UBwsSEbQnkA,1216
220
- osbot_utils/testing/Logging.py,sha256=aOCQGaoKTPAJt3MX2DJoSs-a7UK0KOLqnzn4GRkPFCY,3010
245
+ osbot_utils/testing/Logging.py,sha256=rzO1cCwty1oTucbV1q6U2QBIF87oOcvZoAY_R8SQB8A,3300
221
246
  osbot_utils/testing/Patch_Print.py,sha256=RfY4HGIM06dF6JTKibnN1Uco8YL05xPWe1jS4MUiWV0,1566
222
247
  osbot_utils/testing/Profiler.py,sha256=4em6Lpp0ONRDoDDCZsc_CdAOi_QolKOp4eA7KHN96e4,3365
248
+ osbot_utils/testing/Pytest.py,sha256=R3qdsIXGcNQcu7iobz0RB8AhbbHhc6t757tZoSZRrxA,730
223
249
  osbot_utils/testing/Stderr.py,sha256=wi1gfjpsxnBK3aOl2jzCTWI-0En1HtPgEin97148_MQ,459
224
250
  osbot_utils/testing/Stdout.py,sha256=XQ9OlOW1aHXY1TiNu8O5b75RoDnoaX5RyMHml3OjlKw,459
225
251
  osbot_utils/testing/Temp_File.py,sha256=gL1BJ6aRNg2o4LeUJ4f3bxKc75iw1qp0WKP9T3rS_WU,1435
@@ -235,27 +261,28 @@ osbot_utils/utils/Assert.py,sha256=u9XLgYn91QvNWZGyPi29SjPJSXRHlm9andIn3NJEVog,1
235
261
  osbot_utils/utils/Call_Stack.py,sha256=MAq_0vMxnbeLfCe9qQz7GwJYaOuXpt3qtQwN6wiXsU0,6595
236
262
  osbot_utils/utils/Csv.py,sha256=oHLVpjRJqrLMz9lubMCNEoThXWju5rNTprcwHc1zq2c,1012
237
263
  osbot_utils/utils/Dev.py,sha256=HibpQutYy_iG8gGV8g1GztxNN4l29E4Bi7UZaVL6-L8,1203
238
- osbot_utils/utils/Env.py,sha256=fRYX9cIgbZSjK-Fe8IKiGaBc70-fqRfg6TzFxPgxhwk,4228
264
+ osbot_utils/utils/Env.py,sha256=_7SV5Jor7-GoMggYcwZflTO5D3eQKPvh73FXzC_fyGc,4858
239
265
  osbot_utils/utils/Exceptions.py,sha256=KyOUHkXQ_6jDTq04Xm261dbEZuRidtsM4dgzNwSG8-8,389
240
266
  osbot_utils/utils/Files.py,sha256=HRMdDq1ZctDfCkIfuZGgQ3fG6O03qJEFEIkb8HTYzfU,19407
241
267
  osbot_utils/utils/Functions.py,sha256=0E6alPJ0fJpBiJgFOWooCOi265wSRyxxXAJ5CELBnso,3498
242
268
  osbot_utils/utils/Http.py,sha256=Z8V149M2HDrKBoXkDD5EXgqTGx6vQoUqXugXK__wcuw,4572
243
269
  osbot_utils/utils/Int.py,sha256=PmlUdU4lSwf4gJdmTVdqclulkEp7KPCVUDO6AcISMF4,116
244
- osbot_utils/utils/Json.py,sha256=AfOXYBxAGzqwaNeHZ-aC-RpurNmHzPxGoym7MMY8UN4,6366
270
+ osbot_utils/utils/Json.py,sha256=UNaBazuH1R40fsHjpjuK8kmAANmUHoK9Q0PUeYmgPeY,6254
245
271
  osbot_utils/utils/Json_Cache.py,sha256=mLPkkDZN-3ZVJiDvV1KBJXILtKkTZ4OepzOsDoBPhWg,2006
246
272
  osbot_utils/utils/Lists.py,sha256=CLEjgZwAixJAFlubWEKjnUUhUN85oqvR7UqExVW7rdY,5502
247
- osbot_utils/utils/Misc.py,sha256=AhacU4Wood7-d-mEypPaUUMLEOZyPlVvkOSQa3HRyNU,16784
248
- osbot_utils/utils/Objects.py,sha256=qI6EVvx7kzXQrVGzsDk8txJkIXjsy7m2EEPZnYGy5R0,13867
273
+ osbot_utils/utils/Misc.py,sha256=5pVxQLCOcGNL3PtasOtQCN8ostg2X-H7mucdZjgg_ns,16580
274
+ osbot_utils/utils/Objects.py,sha256=SNtQ1nJnqihwTcmIf_Hg9P3V7fHjxcVHSzC7vKKI34Q,14419
249
275
  osbot_utils/utils/Png.py,sha256=V1juGp6wkpPigMJ8HcxrPDIP4bSwu51oNkLI8YqP76Y,1172
250
276
  osbot_utils/utils/Process.py,sha256=lr3CTiEkN3EiBx3ZmzYmTKlQoPdkgZBRjPulMxG-zdo,2357
251
- osbot_utils/utils/Python_Logger.py,sha256=z_20FlFdaLoUgJ0cmqXnyA7icgFIpBz8Ej1_xVKWsWM,11245
277
+ osbot_utils/utils/Python_Logger.py,sha256=7IPB6gMw-G9HWdgyG_k6d7CE71P55-SAudKgDVxraMs,12756
252
278
  osbot_utils/utils/Status.py,sha256=Yq4s0TelXgn0i2QjCP9V8mP30GabXp_UL-jjM6Iwiw4,4305
253
- osbot_utils/utils/Str.py,sha256=gcStFbB57ol74ASIr00pWImpd6ObBr5BLpSB0VUKNTE,1749
279
+ osbot_utils/utils/Str.py,sha256=kxdY8ROX4FdJtCaMTfOc8fK_xcDICprNkefHu2MMNU4,2585
280
+ osbot_utils/utils/Toml.py,sha256=-bg9srF7ef31UCNFa0aL3CDeDKp14XeUVwRMQzMb_dI,1074
254
281
  osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
255
282
  osbot_utils/utils/Zip.py,sha256=YFahdBguVK71mLdYy4m7mqVAQ5al-60QnTmYK-txCfY,6784
256
283
  osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
257
- osbot_utils/version,sha256=VTpLwd--VoDn3yNbvY_3ModCDIw3sM07Mu6DZ7U1mD8,8
258
- osbot_utils-1.17.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
259
- osbot_utils-1.17.0.dist-info/METADATA,sha256=rLrA0JScCugXwuwBVfq7Uq2FaMHps2la9ukW2oIfIb0,1266
260
- osbot_utils-1.17.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
261
- osbot_utils-1.17.0.dist-info/RECORD,,
284
+ osbot_utils/version,sha256=JmSC-7tQoDn49-PViAeu6VFjLe3IfunvgxhTTKVPaeM,8
285
+ osbot_utils-1.20.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
286
+ osbot_utils-1.20.0.dist-info/METADATA,sha256=ChhDrqyyl82nRtbbQJi0A9b8HjbqfxL7xZXNGIqCID8,1266
287
+ osbot_utils-1.20.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
288
+ osbot_utils-1.20.0.dist-info/RECORD,,