osbot-utils 1.91.0__py3-none-any.whl → 1.93.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.
@@ -3,7 +3,7 @@
3
3
 
4
4
  import sys
5
5
  import types
6
- from osbot_utils.utils.Objects import default_value # todo: remove test mocking requirement for this to be here (instead of on the respective method)
6
+ from osbot_utils.utils.Objects import default_value # todo: remove test mocking requirement for this to be here (instead of on the respective method)
7
7
 
8
8
  # Backport implementations of get_origin and get_args for Python 3.7
9
9
  if sys.version_info < (3, 8): # pragma: no cover
@@ -64,6 +64,24 @@ class Type_Safe:
64
64
  def __enter__(self): return self
65
65
  def __exit__(self, exc_type, exc_val, exc_tb): pass
66
66
 
67
+ def __getattr__(self, name): # Called when an attribute is not found through normal attribute access
68
+ if name.startswith(("set_", "get_")): # Check if the requested attribute is a getter or setter method
69
+ prefix = name[:4] # Extract "set_" or "get_" from the method name
70
+ attr_name = name[4:] # Get the actual attribute name by removing the prefix
71
+
72
+ if hasattr(self, attr_name): # Verify that the target attribute actually exists on the object
73
+ if prefix == "set_": # Handle setter method creation
74
+ def setter(value): # Create a dynamic setter function that takes a value parameter
75
+ setattr(self, attr_name, value) # Set the attribute value using type-safe setattr from Type_Safe
76
+ return self # Return self for method chaining
77
+ return setter # Return the setter function
78
+ else: # get_ # Handle getter method creation
79
+ def getter(): # Create a dynamic getter function with no parameters
80
+ return getattr(self, attr_name) # Return the attribute value using Python's built-in getattr
81
+ return getter # Return the getter function
82
+
83
+ raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") # Raise error if attribute is not a valid getter/setter
84
+
67
85
  def __setattr__(self, name, value):
68
86
  from osbot_utils.utils.Objects import convert_dict_to_value_from_obj_annotation
69
87
  from osbot_utils.utils.Objects import convert_to_value_from_obj_annotation
@@ -77,8 +95,12 @@ class Type_Safe:
77
95
  if value is not None:
78
96
  if type(value) is dict:
79
97
  value = convert_dict_to_value_from_obj_annotation(self, name, value)
80
- if type(value) in [int, str]: # for now only a small number of str and int classes are supported (until we understand the full implications of this)
98
+ elif type(value) in [int, str]: # for now only a small number of str and int classes are supported (until we understand the full implications of this)
81
99
  value = convert_to_value_from_obj_annotation (self, name, value)
100
+ else:
101
+ origin = get_origin(value)
102
+ if origin is not None:
103
+ value = origin
82
104
  check_1 = value_type_matches_obj_annotation_for_attr (self, name, value)
83
105
  check_2 = value_type_matches_obj_annotation_for_union_and_annotated(self, name, value)
84
106
  if (check_1 is False and check_2 is None or
@@ -151,7 +173,7 @@ class Type_Safe:
151
173
  #todo: fix type safety bug that I believe is caused here
152
174
  if obj_is_type_union_compatible(var_type, IMMUTABLE_TYPES) is False: # if var_type is not something like Optional[Union[int, str]]
153
175
  if type(var_type) not in IMMUTABLE_TYPES:
154
- exception_message = f"variable '{var_name}' is defined as type '{var_type}' which is not supported by Kwargs_To_Self, with only the following immutable types being supported: '{IMMUTABLE_TYPES}'"
176
+ exception_message = f"variable '{var_name}' is defined as type '{var_type}' which is not supported by Type_Safe, with only the following immutable types being supported: '{IMMUTABLE_TYPES}'"
155
177
  raise ValueError(exception_message)
156
178
  if include_base_classes is False:
157
179
  break
@@ -286,6 +308,19 @@ class Type_Safe:
286
308
  setattr(self, key, value)
287
309
  return self
288
310
 
311
+ def deserialize_type__using_value(self, value):
312
+ if value:
313
+ try:
314
+ module_name, type_name = value.rsplit('.', 1)
315
+ if module_name == 'builtins' and type_name == 'NoneType': # Special case for NoneType (which serialises as builtins.* , but it actually in types.* )
316
+ value = types.NoneType
317
+ else:
318
+ module = __import__(module_name, fromlist=[type_name])
319
+ value = getattr(module, type_name)
320
+ except (ValueError, ImportError, AttributeError) as e:
321
+ raise ValueError(f"Could not reconstruct type from '{value}': {str(e)}")
322
+ return value
323
+
289
324
  def deserialize_dict__using_key_value_annotations(self, key, value):
290
325
  from osbot_utils.base_classes.Type_Safe__Dict import Type_Safe__Dict
291
326
 
@@ -335,7 +370,9 @@ class Type_Safe:
335
370
  raise ValueError(f"Attribute '{key}' not found in '{self.__class__.__name__}'")
336
371
  else:
337
372
  continue
338
- if obj_is_attribute_annotation_of_type(self, key, dict): # handle the case when the value is a dict
373
+ if obj_attribute_annotation(self, key) == type: # Handle type objects
374
+ value = self.deserialize_type__using_value(value)
375
+ elif obj_is_attribute_annotation_of_type(self, key, dict): # handle the case when the value is a dict
339
376
  value = self.deserialize_dict__using_key_value_annotations(key, value)
340
377
  elif obj_is_attribute_annotation_of_type(self, key, list): # handle the case when the value is a list
341
378
  attribute_annotation = obj_attribute_annotation(self, key) # get the annotation for this variable
@@ -405,15 +442,17 @@ def serialize_to_dict(obj):
405
442
  return obj
406
443
  elif isinstance(obj, Enum):
407
444
  return obj.name
445
+ elif isinstance(obj, type):
446
+ return f"{obj.__module__}.{obj.__name__}" # save the full type name
408
447
  elif isinstance(obj, list) or isinstance(obj, List):
409
448
  return [serialize_to_dict(item) for item in obj]
410
449
  elif isinstance(obj, dict):
411
450
  return {key: serialize_to_dict(value) for key, value in obj.items()}
412
451
  elif hasattr(obj, "__dict__"):
413
- data = {} # todo: look at a more advanced version which saved the type of the object, for example with {'__type__': type(obj).__name__}
452
+ data = {} # todo: look at a more advanced version which saved the type of the object, for example with {'__type__': type(obj).__name__}
414
453
  for key, value in obj.__dict__.items():
415
- if key.startswith('__') is False: # don't process internal variables (for example the ones set by @cache_on_self)
416
- data[key] = serialize_to_dict(value) # Recursive call for complex types
454
+ if key.startswith('__') is False: # don't process internal variables (for example the ones set by @cache_on_self)
455
+ data[key] = serialize_to_dict(value) # Recursive call for complex types
417
456
  return data
418
457
  else:
419
458
  raise TypeError(f"Type {type(obj)} not serializable")
@@ -1,10 +1,6 @@
1
- from enum import Enum
2
-
3
- from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
4
- from osbot_utils.graphs.mermaid.configs.Mermaid__Node__Config import Mermaid__Node__Config
5
- from osbot_utils.graphs.mermaid.models.Mermaid__Node__Shape import Mermaid__Node__Shape
6
- from osbot_utils.graphs.mgraph.MGraph__Node import MGraph__Node
7
- from osbot_utils.utils.Str import safe_str
1
+ from osbot_utils.graphs.mermaid.configs.Mermaid__Node__Config import Mermaid__Node__Config
2
+ from osbot_utils.graphs.mermaid.models.Mermaid__Node__Shape import Mermaid__Node__Shape
3
+ from osbot_utils.graphs.mgraph.MGraph__Node import MGraph__Node
8
4
 
9
5
  LINE_PADDING = ' '
10
6
 
@@ -1,7 +1,7 @@
1
1
  from typing import List
2
2
 
3
3
  from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
4
- from osbot_utils.graphs.mermaid.configs.Mermaid__Render__Config import Mermaid__Render__Config
4
+ from osbot_utils.graphs.mermaid.configs.Mermaid__Render__Config import Mermaid__Render__Config
5
5
  from osbot_utils.graphs.mermaid.models.Mermaid__Diagram_Direction import Diagram__Direction
6
6
  from osbot_utils.graphs.mermaid.models.Mermaid__Diagram__Type import Diagram__Type
7
7
 
@@ -1,8 +1,5 @@
1
- from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
2
- from osbot_utils.graphs.mermaid.Mermaid__Node import LINE_PADDING, Mermaid__Node
1
+ from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
3
2
  from osbot_utils.graphs.mgraph.MGraph__Node import MGraph__Node
4
- from osbot_utils.utils.Str import safe_str
5
-
6
3
 
7
4
  class MGraph__Edge(Kwargs_To_Self):
8
5
  attributes : dict
@@ -1,6 +1,5 @@
1
- from osbot_utils.utils.Misc import random_id
2
-
3
- from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
1
+ from osbot_utils.utils.Misc import random_id
2
+ from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
4
3
 
5
4
 
6
5
  class MGraph__Node(Kwargs_To_Self):
@@ -1,9 +1,8 @@
1
- from enum import Enum, auto
2
- from osbot_utils.utils.Str import safe_str
3
- from osbot_utils.helpers.Local_Cache import Local_Cache
4
-
1
+ from enum import Enum, auto
2
+ from osbot_utils.utils.Str import safe_str
3
+ from osbot_utils.helpers.Local_Cache import Local_Cache
5
4
  from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
6
- from osbot_utils.graphs.mgraph.MGraph import MGraph
5
+ from osbot_utils.graphs.mgraph.MGraph import MGraph
7
6
 
8
7
 
9
8
  class Serialization_Mode(Enum):
@@ -1,10 +1,5 @@
1
- import random
2
-
3
- from osbot_utils.utils.Files import file_exists, file_extension, pickle_load_from_file
4
-
5
1
  from osbot_utils.graphs.mgraph.MGraph__Random_Graphs import MGraph__Random_Graphs
6
2
 
7
-
8
3
  class MGraphs:
9
4
 
10
5
  def new__random(self, config=None, graph_key=None, x_nodes=10, y_edges=20):
@@ -1,8 +1,10 @@
1
1
  from osbot_utils.utils.Misc import random_id_short
2
2
  from osbot_utils.utils.Str import safe_id
3
3
 
4
+ SAFE_ID__MAX_LENGTH = 512
5
+
4
6
  class Safe_Id(str):
5
- def __new__(cls, value=None, max_length=36):
7
+ def __new__(cls, value=None, max_length=SAFE_ID__MAX_LENGTH):
6
8
  if value is None:
7
9
  value = safe_id(random_id_short('safe-id'))
8
10
  sanitized_value = safe_id(value, max_length=max_length)
@@ -25,13 +25,14 @@ class RSS__Feed__Parser:
25
25
  guid = self.extract_guid(item_data.get('guid' ))
26
26
  pubDate = self.element_text(item_data.get('pubDate' ))
27
27
  creator = self.element_text(item_data.get('creator' ))
28
+ categories = self.ensure_is_list(item_data.get('category'))
28
29
  rss_item = RSS__Item(title = title ,
29
30
  link = link ,
30
31
  description = description ,
31
32
  guid = guid ,
32
33
  pubDate = pubDate ,
33
34
  creator = creator ,
34
- categories = item_data.get('category' , []),
35
+ categories = categories ,
35
36
  content = item_data.get('content' , {}),
36
37
  thumbnail = item_data.get('thumbnail' , {}))
37
38
 
@@ -74,6 +75,15 @@ class RSS__Feed__Parser:
74
75
  def extract_guid(self, target):
75
76
  return Guid(self.extract_text(target))
76
77
 
78
+ def ensure_is_list(self, target):
79
+ if type(target) is list:
80
+ return target
81
+ if type(target) is str:
82
+ return [target]
83
+ if target:
84
+ return [f'{target}']
85
+ return []
86
+
77
87
  def element_text(self, target):
78
88
  if isinstance(target, list):
79
89
  for item in target:
osbot_utils/utils/Json.py CHANGED
@@ -193,6 +193,7 @@ json_save_file_gz = Json.save_file_gz
193
193
  json_save_file_pretty_gz = Json.save_file_pretty_gz
194
194
  json_save_tmp_file = Json.json_save_tmp_file
195
195
  str_to_json = Json.loads
196
+ str_from_json = json_dumps
196
197
 
197
198
  load_file_json = json_load_file
198
199
  load_file_json_gz = json_load_file_gz
@@ -359,8 +359,6 @@ def obj_attribute_annotation(target, attr_name):
359
359
 
360
360
  def obj_is_attribute_annotation_of_type(target, attr_name, expected_type):
361
361
  attribute_annotation = obj_attribute_annotation(target, attr_name)
362
- #attribute_type = type(attribute_annotation)
363
- #return attribute_type is expected_type
364
362
  if expected_type is attribute_annotation:
365
363
  return True
366
364
  if expected_type is type(attribute_annotation):
osbot_utils/utils/Str.py CHANGED
@@ -42,7 +42,7 @@ def safe_id(value, max_length=36):
42
42
  value = str(value)
43
43
 
44
44
  if len(value) > max_length:
45
- raise ValueError(f"Invalid ID: The ID must not exceed 36 characters (was {len(value)}).")
45
+ raise ValueError(f"Invalid ID: The ID must not exceed {max_length} characters (was {len(value)}).")
46
46
 
47
47
  sanitized_value = REGEX__SAFE_ID_REGEX.sub('_', value)
48
48
 
osbot_utils/version CHANGED
@@ -1 +1 @@
1
- v1.91.0
1
+ v1.93.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: osbot_utils
3
- Version: 1.91.0
3
+ Version: 1.93.0
4
4
  Summary: OWASP Security Bot - Utils
5
5
  Home-page: https://github.com/owasp-sbot/OSBot-Utils
6
6
  License: MIT
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
23
23
 
24
24
  Powerful Python util methods and classes that simplify common apis and tasks.
25
25
 
26
- ![Current Release](https://img.shields.io/badge/release-v1.91.0-blue)
26
+ ![Current Release](https://img.shields.io/badge/release-v1.93.0-blue)
27
27
  [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](https://codecov.io/gh/owasp-sbot/OSBot-Utils)
28
28
 
29
29
 
@@ -2,7 +2,7 @@ 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
4
  osbot_utils/base_classes/Kwargs_To_Self.py,sha256=weFNsBfBNV9W_qBkN-IdBD4yYcJV_zgTxBRO-ZlcPS4,141
5
- osbot_utils/base_classes/Type_Safe.py,sha256=JT_lzMkdt7zmLFAPProbgk30J3iBjLgpavGOZ7XwvXY,25611
5
+ osbot_utils/base_classes/Type_Safe.py,sha256=XzJd1tOEFFT67ycg5QaiXv5pFeWD8Fq4YDVQGGVYAjc,28990
6
6
  osbot_utils/base_classes/Type_Safe__Base.py,sha256=CFPYe8_i5vvTLyc7s8CXbY4n_dY6sqVfBY8w9Vo77ZA,5468
7
7
  osbot_utils/base_classes/Type_Safe__Dict.py,sha256=sfZcukhXUd9TS0PQpAk-gGLfZUJSC6BtMh6jF4Fn8Jw,1107
8
8
  osbot_utils/base_classes/Type_Safe__List.py,sha256=pXDzJJttpEQQ9oTdsw7BykMB4VIX2rZzi1ZrnCzMZ8M,650
@@ -41,8 +41,8 @@ osbot_utils/graphs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
41
41
  osbot_utils/graphs/mermaid/Mermaid.py,sha256=G7--iIKm2C1z-tEB1qLNopwoW3_w4oR7Oq7-yA460mM,3164
42
42
  osbot_utils/graphs/mermaid/Mermaid__Edge.py,sha256=jwHxHJEAA49aO28T8nnJFxOfpWAZZaWKNT_krG1fwkQ,1893
43
43
  osbot_utils/graphs/mermaid/Mermaid__Graph.py,sha256=FRw17efZrdcKyXDKsyb1C8nswIAmljiUAyiF0FHIL4M,2854
44
- osbot_utils/graphs/mermaid/Mermaid__Node.py,sha256=j_AVfR3hnKAJH2Z3d17djvU7MfQP8B70Lh7Jv6y0tTs,3322
45
- osbot_utils/graphs/mermaid/Mermaid__Renderer.py,sha256=-5h_Xkaq3boKVWzPYPG_kUoe0SOlR0Tm4zVEXJ70wUk,2289
44
+ osbot_utils/graphs/mermaid/Mermaid__Node.py,sha256=e_DO1SGnf6Zdh4ZvcRBhonDicgKGu86VDN9gd9tP7Gc,3215
45
+ osbot_utils/graphs/mermaid/Mermaid__Renderer.py,sha256=Uoy_y43zeKqKUYj0V2FMK9CKFweutUY5r4IjsD0Z7RU,2293
46
46
  osbot_utils/graphs/mermaid/configs/Mermaid__Edge__Config.py,sha256=PaypnkaDQQhNBIxZqnAB5bxuJAZWh3SQtmHUPfIcDCQ,212
47
47
  osbot_utils/graphs/mermaid/configs/Mermaid__Node__Config.py,sha256=KZWd_uiIm-QIz_wPSDfXfWAWU_A2yxzMeq-h5wldVjQ,465
48
48
  osbot_utils/graphs/mermaid/configs/Mermaid__Render__Config.py,sha256=JGQR6kdiTQh45zFZYvqdEDMghFIWLnVYMZsdukYtGyw,216
@@ -53,11 +53,11 @@ osbot_utils/graphs/mermaid/models/Mermaid__Node__Shape.py,sha256=_su5S8nYqg5qpXm
53
53
  osbot_utils/graphs/mgraph/MGraph.py,sha256=1Iu2CM9IHxoJxjmABsBqDvi8l09LINLDE9_b53Dz4kM,2218
54
54
  osbot_utils/graphs/mgraph/MGraph__Config.py,sha256=oFTj9eP92HolaOSyk-7tpsPVFZLMIcTH-O-mx93nTiA,204
55
55
  osbot_utils/graphs/mgraph/MGraph__Data.py,sha256=oLaKmxUOXoQbhdUxa_VW_QZA0tAETgRMzP3pvslppHw,5746
56
- osbot_utils/graphs/mgraph/MGraph__Edge.py,sha256=TnYUk6-YFpB3_6zY-CY6jJFVSLciGbCxE-fuABw9LX4,916
57
- osbot_utils/graphs/mgraph/MGraph__Node.py,sha256=WPdAzd74sbWm4nD4ELH23g52I5mNHu5KjHDOk38qMIY,876
56
+ osbot_utils/graphs/mgraph/MGraph__Edge.py,sha256=sS9LojdWZ8AISD0d8gdY6HgcyPM956roHmEkzhM_TQg,785
57
+ osbot_utils/graphs/mgraph/MGraph__Node.py,sha256=KnUnD918hu5ifjbW_v7AVAAzxjHi5iuA4rluvDGOaPg,893
58
58
  osbot_utils/graphs/mgraph/MGraph__Random_Graphs.py,sha256=MDCmnrv7QcGXJeZDYc4y5Wth6ysB0hHzn1DqfocxtIs,964
59
- osbot_utils/graphs/mgraph/MGraph__Serializer.py,sha256=F8epC-55qMyBZiMD5SLPVmLgIKj2iosiblb7heTH_cQ,1408
60
- osbot_utils/graphs/mgraph/MGraphs.py,sha256=W8GlTBQ-1nBb9Zj3nbZ3QetyaP1LlkhMBVOiOLIsCE4,636
59
+ osbot_utils/graphs/mgraph/MGraph__Serializer.py,sha256=pLgKsJuo1x8S22m6TCLd3bvFLrBo6sTrq1AkknkOA18,1475
60
+ osbot_utils/graphs/mgraph/MGraphs.py,sha256=TIv1CEsUiPIVxll3AuGLhEVBY4YRzZu_rpEz3Tzrph8,532
61
61
  osbot_utils/graphs/mgraph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
62
  osbot_utils/helpers/CFormat.py,sha256=1_XvqGwgU6qC97MbzcKF0o7s9mCXpU5Kq9Yf-1ixUwY,6808
63
63
  osbot_utils/helpers/CPrint.py,sha256=ztKPNmT8BGxeyPXSQKRs63PqqbgxKDz_BiZmzFMup9g,1413
@@ -72,7 +72,7 @@ osbot_utils/helpers/Python_Audit.py,sha256=shpZlluJwqJBAlad6xN01FkgC1TsQ48RLvR5Z
72
72
  osbot_utils/helpers/Random_Guid.py,sha256=COu9hcP51vzjk-ErECTFFaOWuOmW0eGJyMu8HXhaRXQ,382
73
73
  osbot_utils/helpers/Random_Guid_Short.py,sha256=YP_k5OLuYvXWGU2OEnQHk_OGViBQofTWKm3pUdQaJao,404
74
74
  osbot_utils/helpers/Random_Seed.py,sha256=14btja8LDN9cMGWaz4fCNcMRU_eyx49gas-_PQvHgy4,634
75
- osbot_utils/helpers/Safe_Id.py,sha256=iwIrWXfSARyr6JkihNhh1soOdjeCGVf3wkXSkSP8zDw,402
75
+ osbot_utils/helpers/Safe_Id.py,sha256=0wPGd9eLzaOCYTSg9yEOal1kPsc8OI9khHkqEw9VQOM,446
76
76
  osbot_utils/helpers/Str_ASCII.py,sha256=PRqyu449XnKrLn6b9Miii1Hv-GO5OAa1UhhgvlRcC2M,704
77
77
  osbot_utils/helpers/Timestamp_Now.py,sha256=k3-SUGYx2jLTXvgZYeECqPRJhVxqWPmW7co1l6r12jk,438
78
78
  osbot_utils/helpers/Type_Registry.py,sha256=Ajk3SyMSKDi2g9SJYUtTgg7PZkAgydaHcpbGuEN3S94,311
@@ -288,7 +288,7 @@ osbot_utils/helpers/xml/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
288
288
  osbot_utils/helpers/xml/rss/RSS__Channel.py,sha256=HPLsGRNIaPh0_8GYE2a53bSV5Bb4E6j6tKGuy4bxg4Y,605
289
289
  osbot_utils/helpers/xml/rss/RSS__Enclosure.py,sha256=f75U7nXXJ7hLs2zPDui0WsFAmMJaeaverjlxD4M-Otg,142
290
290
  osbot_utils/helpers/xml/rss/RSS__Feed.py,sha256=lhFoeBMWdH1Dp8QnagCGj9bfZHKmB_HkE56hPVZNaM0,425
291
- osbot_utils/helpers/xml/rss/RSS__Feed__Parser.py,sha256=qG4FbUexMmU6_pTgcxDBmBeZvh9d1dmFZGzQOwVlggk,5088
291
+ osbot_utils/helpers/xml/rss/RSS__Feed__Parser.py,sha256=7sub6zcWqGz8FORXFYRyopTswboUkCU5uGEXAZ6BZDw,5380
292
292
  osbot_utils/helpers/xml/rss/RSS__Image.py,sha256=4uI0jd17pqb8FJ8HQcERXvn3WjGbiOVI8u1tv-IN59U,171
293
293
  osbot_utils/helpers/xml/rss/RSS__Item.py,sha256=y-QI2WBfd9FEsVWc_eNirvZUUslpb2z27hxcm-RVHJQ,611
294
294
  osbot_utils/testing/Catch.py,sha256=HdNoKnrPBjvVj87XYN-Wa1zpo5z3oByURT6TKbd5QpQ,2229
@@ -323,24 +323,24 @@ osbot_utils/utils/Files.py,sha256=yxteAcyhDcUy1_r9Eihx80V16lV_UAE6cvoOe2Dc7DU,23
323
323
  osbot_utils/utils/Functions.py,sha256=0E6alPJ0fJpBiJgFOWooCOi265wSRyxxXAJ5CELBnso,3498
324
324
  osbot_utils/utils/Http.py,sha256=Cm_-b2EgxKoQJ47ThZp-dgHCdeGv4UcCNLfTOH94-7s,7790
325
325
  osbot_utils/utils/Int.py,sha256=PmlUdU4lSwf4gJdmTVdqclulkEp7KPCVUDO6AcISMF4,116
326
- osbot_utils/utils/Json.py,sha256=0DZGlCU7Nqte5n0r7ctPXFybqA5MRfSrTz5zuK_6UFk,7095
326
+ osbot_utils/utils/Json.py,sha256=0t7Hwefx8bg4JiZVr-xIbWP3BAk6_ZsnY7iV5pnRLDQ,7137
327
327
  osbot_utils/utils/Json_Cache.py,sha256=mLPkkDZN-3ZVJiDvV1KBJXILtKkTZ4OepzOsDoBPhWg,2006
328
328
  osbot_utils/utils/Lists.py,sha256=tPz5x5s3sRO97WZ_nsxREBPC5cwaHrhgaYBhsrffTT8,5599
329
329
  osbot_utils/utils/Misc.py,sha256=H_xexJgiTxB3jDeDiW8efGQbO0Zuy8MM0iQ7qXC92JI,17363
330
- osbot_utils/utils/Objects.py,sha256=FVX0CyVY2g1iXIL4UA1dFzgbsA-GYrJ_cYlxosGxTdo,21713
330
+ osbot_utils/utils/Objects.py,sha256=nsheXk2t4sRQVJStsKYDgCj8wF3knQ8X1AtLO1M4SlM,21614
331
331
  osbot_utils/utils/Png.py,sha256=V1juGp6wkpPigMJ8HcxrPDIP4bSwu51oNkLI8YqP76Y,1172
332
332
  osbot_utils/utils/Process.py,sha256=lr3CTiEkN3EiBx3ZmzYmTKlQoPdkgZBRjPulMxG-zdo,2357
333
333
  osbot_utils/utils/Python_Logger.py,sha256=tx8N6wRKL3RDHboDRKZn8SirSJdSAE9cACyJkxrThZ8,12792
334
334
  osbot_utils/utils/Regex.py,sha256=MtHhk69ax7Nwu4CQZK7y4KXHZ6VREwEpIchuioB168c,960
335
335
  osbot_utils/utils/Status.py,sha256=Yq4s0TelXgn0i2QjCP9V8mP30GabXp_UL-jjM6Iwiw4,4305
336
- osbot_utils/utils/Str.py,sha256=Y05F46m6s3_H7KoPdeasc1LRaU7R4YifIbsHNQYDEeg,3275
336
+ osbot_utils/utils/Str.py,sha256=6TS_DyWDfNfjK9JrEC7cAkqRU-0U7zBFYZDTMQkKPG0,3285
337
337
  osbot_utils/utils/Threads.py,sha256=lnh4doZWYUIoWBZRU_780QPeAIKGDh7INuqmU8Fzmdc,3042
338
338
  osbot_utils/utils/Toml.py,sha256=Rxl8gx7mni5CvBAK-Ai02EKw-GwtJdd3yeHT2kMloik,1667
339
339
  osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
340
340
  osbot_utils/utils/Zip.py,sha256=pR6sKliUY0KZXmqNzKY2frfW-YVQEVbLKiyqQX_lc-8,14052
341
341
  osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
342
- osbot_utils/version,sha256=mY1aZ-j7A_cOD1nfZEVe-d0NfwVf728QcJbLk0BIvkI,8
343
- osbot_utils-1.91.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
344
- osbot_utils-1.91.0.dist-info/METADATA,sha256=luU4ieNWlaNSKRUyf9jTUyGb2tKGwRPlZtgZ5cZCTPc,1317
345
- osbot_utils-1.91.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
346
- osbot_utils-1.91.0.dist-info/RECORD,,
342
+ osbot_utils/version,sha256=fCgkUd9gyG9PiBtqwiUTRF7MK2o3-3SPgYURno8TnxU,8
343
+ osbot_utils-1.93.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
344
+ osbot_utils-1.93.0.dist-info/METADATA,sha256=FiD0UZFCc7gZG4TyyE4JteDBmpCFyBIeU0w72FsCCPI,1317
345
+ osbot_utils-1.93.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
346
+ osbot_utils-1.93.0.dist-info/RECORD,,