osbot-utils 2.77.0__py3-none-any.whl → 2.79.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.
- osbot_utils/helpers/Dict_To_Attr.py +0 -3
- osbot_utils/helpers/transformers/Dict__To__Toml.py +211 -0
- osbot_utils/type_safe/type_safe_core/methods/Type_Safe__Method.py +25 -6
- osbot_utils/utils/Toml.py +7 -26
- osbot_utils/version +1 -1
- {osbot_utils-2.77.0.dist-info → osbot_utils-2.79.0.dist-info}/METADATA +2 -2
- {osbot_utils-2.77.0.dist-info → osbot_utils-2.79.0.dist-info}/RECORD +9 -8
- {osbot_utils-2.77.0.dist-info → osbot_utils-2.79.0.dist-info}/LICENSE +0 -0
- {osbot_utils-2.77.0.dist-info → osbot_utils-2.79.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,211 @@
|
|
1
|
+
from typing import Dict, Any, List, Set, Tuple, Union
|
2
|
+
from osbot_utils.type_safe.Type_Safe import Type_Safe
|
3
|
+
from osbot_utils.type_safe.type_safe_core.decorators.type_safe import type_safe
|
4
|
+
|
5
|
+
|
6
|
+
class Dict__To__Toml(Type_Safe):
|
7
|
+
|
8
|
+
@type_safe
|
9
|
+
def convert(self, data: Dict[str, Any] # Dictionary to convert to TOML
|
10
|
+
) -> str: # Returns TOML formatted string
|
11
|
+
toml_str = ""
|
12
|
+
|
13
|
+
# First, process top-level simple values
|
14
|
+
toml_str += self._process_simple_values(data, indent_level=0)
|
15
|
+
|
16
|
+
# Process top-level arrays of simple types
|
17
|
+
toml_str += self._process_simple_arrays(data, indent_level=0)
|
18
|
+
|
19
|
+
# Process top-level dictionaries as sections
|
20
|
+
toml_str += self._process_sections(data, parent_key="")
|
21
|
+
|
22
|
+
# Process arrays of tables
|
23
|
+
toml_str += self._process_array_of_tables(data, parent_key="")
|
24
|
+
|
25
|
+
return toml_str
|
26
|
+
|
27
|
+
@type_safe
|
28
|
+
def _format_string_value(self, value: str # String to format
|
29
|
+
) -> str: # Returns formatted TOML string
|
30
|
+
"""Format a string value for TOML output"""
|
31
|
+
# For TOML basic strings, we need to handle:
|
32
|
+
# 1. If string contains single quotes, use double quotes
|
33
|
+
# 2. If string contains double quotes but no single quotes, use single quotes
|
34
|
+
# 3. If string contains both, use triple quotes (multi-line literal)
|
35
|
+
|
36
|
+
has_single = "'" in value
|
37
|
+
has_double = '"' in value
|
38
|
+
has_newline = '\n' in value or '\r' in value
|
39
|
+
|
40
|
+
# Use triple quotes for complex strings (multilineelif has_single: or with both quote types)
|
41
|
+
if has_newline or (has_single and has_double):
|
42
|
+
# Use multi-line literal string (triple single quotes)
|
43
|
+
# This preserves the exact content without escaping
|
44
|
+
return f"'''\n{value}'''"
|
45
|
+
elif has_single:
|
46
|
+
# Use double quotes and escape any double quotes
|
47
|
+
escaped = value.replace('"', '\\"')
|
48
|
+
return f'"{escaped}"'
|
49
|
+
else:
|
50
|
+
# Use single quotes (default) - no escaping needed
|
51
|
+
return f"'{value}'"
|
52
|
+
|
53
|
+
@type_safe
|
54
|
+
def _process_simple_values(self, data : Dict[str, Any] , # Data to process
|
55
|
+
indent_level : int = 0 # Current indentation level
|
56
|
+
) -> str: # Returns TOML for simple values
|
57
|
+
toml_str = ""
|
58
|
+
indent = " " * indent_level
|
59
|
+
|
60
|
+
for key, value in data.items():
|
61
|
+
if not isinstance(value, (dict, list, tuple, set)):
|
62
|
+
if isinstance(value, str):
|
63
|
+
toml_str += f"{indent}{key} = {self._format_string_value(value)}\n"
|
64
|
+
elif isinstance(value, bool):
|
65
|
+
toml_str += f"{indent}{key} = {str(value).lower()}\n"
|
66
|
+
elif value is not None:
|
67
|
+
toml_str += f"{indent}{key} = {value}\n"
|
68
|
+
|
69
|
+
return toml_str
|
70
|
+
|
71
|
+
@type_safe
|
72
|
+
def _process_simple_arrays(self, data : Dict[str, Any] , # Data to process
|
73
|
+
indent_level : int = 0 # Current indentation level
|
74
|
+
) -> str: # Returns TOML for simple arrays
|
75
|
+
toml_str = ""
|
76
|
+
indent = " " * indent_level
|
77
|
+
|
78
|
+
for key, value in data.items():
|
79
|
+
if isinstance(value, (list, tuple, set)):
|
80
|
+
if not value: # Empty collection
|
81
|
+
toml_str += f"{indent}{key} = []\n"
|
82
|
+
elif not any(isinstance(item, dict) for item in value): # No dict items
|
83
|
+
toml_str += f"{indent}{key} = [\n"
|
84
|
+
for item in value:
|
85
|
+
if isinstance(item, str):
|
86
|
+
toml_str += f"{indent} {self._format_string_value(item)},\n"
|
87
|
+
elif isinstance(item, bool):
|
88
|
+
toml_str += f"{indent} {str(item).lower()},\n"
|
89
|
+
elif item is not None:
|
90
|
+
toml_str += f"{indent} {item},\n"
|
91
|
+
toml_str += f"{indent}]\n"
|
92
|
+
|
93
|
+
return toml_str
|
94
|
+
|
95
|
+
@type_safe
|
96
|
+
def _process_sections(self, data : Dict[str, Any] , # Data to process
|
97
|
+
parent_key : str = "" # Parent section key
|
98
|
+
) -> str: # Returns TOML sections
|
99
|
+
toml_str = ""
|
100
|
+
|
101
|
+
for key, value in data.items():
|
102
|
+
if isinstance(value, dict):
|
103
|
+
section_key = f"{parent_key}.{key}" if parent_key else key
|
104
|
+
toml_str += f"[{section_key}]\n"
|
105
|
+
toml_str += self._process_section_content(value, section_key)
|
106
|
+
|
107
|
+
return toml_str
|
108
|
+
|
109
|
+
@type_safe
|
110
|
+
def _process_section_content(self, section_data : Dict[str, Any] , # Section data to process
|
111
|
+
section_key : str # Current section key
|
112
|
+
) -> str: # Returns section content
|
113
|
+
toml_str = ""
|
114
|
+
indent = " "
|
115
|
+
|
116
|
+
# Process simple values in section
|
117
|
+
for key, value in section_data.items():
|
118
|
+
if isinstance(value, str):
|
119
|
+
toml_str += f"{indent}{key} = {self._format_string_value(value)}\n"
|
120
|
+
elif isinstance(value, bool):
|
121
|
+
toml_str += f"{indent}{key} = {str(value).lower()}\n"
|
122
|
+
elif isinstance(value, (int, float)) and value is not None:
|
123
|
+
toml_str += f"{indent}{key} = {value}\n"
|
124
|
+
elif isinstance(value, (list, tuple, set)) and not value:
|
125
|
+
toml_str += f"{indent}{key} = []\n"
|
126
|
+
elif isinstance(value, (list, tuple, set)):
|
127
|
+
if not any(isinstance(item, dict) for item in value):
|
128
|
+
toml_str += f"{indent}{key} = [\n"
|
129
|
+
for item in value:
|
130
|
+
if isinstance(item, str):
|
131
|
+
toml_str += f"{indent}{indent}{self._format_string_value(item)},\n"
|
132
|
+
elif isinstance(item, bool):
|
133
|
+
toml_str += f"{indent}{indent}{str(item).lower()},\n"
|
134
|
+
elif item is not None:
|
135
|
+
toml_str += f"{indent}{indent}{item},\n"
|
136
|
+
toml_str += f"{indent}]\n"
|
137
|
+
|
138
|
+
# Process arrays of tables within sections (NEW)
|
139
|
+
for key, value in section_data.items():
|
140
|
+
if isinstance(value, (list, tuple, set)):
|
141
|
+
if value and all(isinstance(item, dict) for item in value):
|
142
|
+
for item in value:
|
143
|
+
toml_str += f"[[{section_key}.{key}]]\n"
|
144
|
+
for item_key, item_value in item.items():
|
145
|
+
if isinstance(item_value, str):
|
146
|
+
toml_str += f"{indent}{item_key} = {self._format_string_value(item_value)}\n"
|
147
|
+
elif isinstance(item_value, bool):
|
148
|
+
toml_str += f"{indent}{item_key} = {str(item_value).lower()}\n"
|
149
|
+
elif isinstance(item_value, (int, float)) and item_value is not None:
|
150
|
+
toml_str += f"{indent}{item_key} = {item_value}\n"
|
151
|
+
|
152
|
+
# Process nested dictionaries
|
153
|
+
for key, value in section_data.items():
|
154
|
+
if isinstance(value, dict):
|
155
|
+
nested_key = f"{section_key}.{key}"
|
156
|
+
toml_str += f"[{nested_key}]\n"
|
157
|
+
toml_str += self._process_section_content(value, nested_key)
|
158
|
+
|
159
|
+
return toml_str
|
160
|
+
|
161
|
+
@type_safe
|
162
|
+
def _process_array_of_tables(self, data : Dict[str, Any] , # Data to process
|
163
|
+
parent_key : str = "" # Parent section key
|
164
|
+
) -> str: # Returns array of tables
|
165
|
+
toml_str = ""
|
166
|
+
|
167
|
+
for key, value in data.items():
|
168
|
+
if isinstance(value, (list, tuple, set)):
|
169
|
+
if value and all(isinstance(item, dict) for item in value):
|
170
|
+
for item in value:
|
171
|
+
section_key = f"{parent_key}.{key}" if parent_key else key
|
172
|
+
toml_str += f"[[{section_key}]]\n"
|
173
|
+
toml_str += self._process_table_item(item, section_key)
|
174
|
+
|
175
|
+
return toml_str
|
176
|
+
|
177
|
+
@type_safe
|
178
|
+
def _process_table_item(self, item : Dict[str, Any] , # Table item to process
|
179
|
+
section_key : str # Current section key
|
180
|
+
) -> str: # Returns formatted table item
|
181
|
+
toml_str = ""
|
182
|
+
indent = " "
|
183
|
+
|
184
|
+
# Process simple values in table item
|
185
|
+
for key, value in item.items():
|
186
|
+
if isinstance(value, str):
|
187
|
+
toml_str += f"{indent}{key} = {self._format_string_value(value)}\n"
|
188
|
+
elif isinstance(value, bool):
|
189
|
+
toml_str += f"{indent}{key} = {str(value).lower()}\n"
|
190
|
+
elif isinstance(value, (int, float)) and value is not None:
|
191
|
+
toml_str += f"{indent}{key} = {value}\n"
|
192
|
+
elif isinstance(value, (list, tuple, set)) and not value:
|
193
|
+
toml_str += f"{indent}{key} = []\n"
|
194
|
+
elif isinstance(value, (list, tuple, set)):
|
195
|
+
if not any(isinstance(sub_item, dict) for sub_item in value):
|
196
|
+
toml_str += f"{indent}{key} = [\n"
|
197
|
+
for sub_item in value:
|
198
|
+
if isinstance(sub_item, str):
|
199
|
+
toml_str += f"{indent}{indent}{self._format_string_value(sub_item)},\n"
|
200
|
+
else:
|
201
|
+
toml_str += f"{indent}{indent}{sub_item},\n"
|
202
|
+
toml_str += f"{indent}]\n"
|
203
|
+
|
204
|
+
# Process nested dicts in table items
|
205
|
+
for key, value in item.items():
|
206
|
+
if isinstance(value, dict):
|
207
|
+
nested_section = f"{section_key}.{key}"
|
208
|
+
toml_str += f"[{nested_section}]\n"
|
209
|
+
toml_str += self._process_section_content(value, nested_section)
|
210
|
+
|
211
|
+
return toml_str
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import collections
|
1
2
|
import inspect # For function introspection
|
2
3
|
from enum import Enum
|
3
4
|
from typing import get_args, get_origin, Union, List, Any, Dict # For type hinting utilities
|
@@ -105,14 +106,32 @@ class Type_Safe__Method:
|
|
105
106
|
if not isinstance(param_value, list): # Check if value is a list
|
106
107
|
raise ValueError(f"Parameter '{param_name}' expected a list but got {type(param_value)}") # Raise error if not list
|
107
108
|
|
108
|
-
item_type = get_args(expected_type)[0]
|
109
|
-
|
109
|
+
item_type = get_args(expected_type)[0] # Get list item type
|
110
|
+
item_origin = get_origin(item_type) # Get origin of item type
|
111
|
+
|
112
|
+
if item_origin is dict or item_origin is Dict: # Handle Dict[K, V] items
|
113
|
+
key_type, value_type = get_args(item_type) # Extract key and value types
|
114
|
+
for i, item in enumerate(param_value): # Validate each dict in list
|
115
|
+
if not isinstance(item, dict): # Check item is a dict
|
116
|
+
raise ValueError(f"List item at index {i} expected dict but got {type(item)}") # Raise error if not dict
|
117
|
+
for k, v in item.items(): # Validate dict contents
|
118
|
+
if not isinstance(k, key_type): # Check key type
|
119
|
+
raise ValueError(f"Dict key '{k}' at index {i} expected type {key_type}, but got {type(k)}") # Raise error for invalid key
|
120
|
+
if not isinstance(v, value_type): # Check value type
|
121
|
+
raise ValueError(f"Dict value for key '{k}' at index {i} expected type {value_type}, but got {type(v)}") # Raise error for invalid value
|
122
|
+
elif item_origin is collections.abc.Callable: # Handle Callable[[...], ...] items
|
123
|
+
for i, item in enumerate(param_value): # Validate each callable in list
|
124
|
+
if not callable(item): # Check item is callable
|
125
|
+
raise ValueError(f"List item at index {i} expected callable but got {type(item)}") # Raise error if not callable
|
126
|
+
# Note: Full signature validation would require is_callable_compatible method
|
127
|
+
elif item_origin is not None: # Handle other subscripted types
|
110
128
|
raise NotImplementedError(f"Validation for list items with subscripted type"
|
111
129
|
f" '{item_type}' is not yet supported "
|
112
|
-
f"in parameter '{param_name}'.")
|
113
|
-
|
114
|
-
|
115
|
-
|
130
|
+
f"in parameter '{param_name}'.") # todo: add support for checking for subscripted types
|
131
|
+
else: # Handle non-subscripted types
|
132
|
+
for i, item in enumerate(param_value): # Check each list item
|
133
|
+
if not isinstance(item, item_type): # Validate item type
|
134
|
+
raise ValueError(f"List item at index {i} expected type {item_type}, but got {type(item)}") # Raise error for invalid item
|
116
135
|
|
117
136
|
def validate_type_parameter(self, param_name: str, param_value: Any, expected_type: Any): # Validate a Type[T] parameter
|
118
137
|
if not isinstance(param_value, type):
|
osbot_utils/utils/Toml.py
CHANGED
@@ -1,29 +1,11 @@
|
|
1
1
|
import sys
|
2
|
-
from osbot_utils.
|
3
|
-
from osbot_utils.utils.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
for key, value in data.items():
|
11
|
-
if isinstance(value, dict):
|
12
|
-
toml_str += f"{indent}[{key}]\n"
|
13
|
-
toml_str += dict_to_toml(value, indent_level + 1)
|
14
|
-
elif isinstance(value, (list, tuple, set)):
|
15
|
-
toml_str += f"{indent}{key} = [\n"
|
16
|
-
for item in value:
|
17
|
-
toml_str += f"{indent} {repr(item)},\n"
|
18
|
-
toml_str += f"{indent}]\n"
|
19
|
-
elif isinstance(value, str):
|
20
|
-
toml_str += f"{indent}{key} = '{value}'\n"
|
21
|
-
elif isinstance(value, bool):
|
22
|
-
toml_str += f"{indent}{key} = {str(value).lower()}\n"
|
23
|
-
else:
|
24
|
-
toml_str += f"{indent}{key} = {value}\n"
|
25
|
-
|
26
|
-
return toml_str
|
2
|
+
from osbot_utils.helpers.transformers.Dict__To__Toml import Dict__To__Toml
|
3
|
+
from osbot_utils.utils.Files import file_create, file_contents
|
4
|
+
from osbot_utils.utils.Objects import dict_to_obj
|
5
|
+
|
6
|
+
|
7
|
+
def dict_to_toml(data):
|
8
|
+
return Dict__To__Toml().convert(data) # Singleton instance for convenience
|
27
9
|
|
28
10
|
def toml_dict_to_file(toml_file, data):
|
29
11
|
str_toml = dict_to_toml(data)
|
@@ -33,7 +15,6 @@ def toml_dict_from_file(toml_file):
|
|
33
15
|
str_toml = file_contents(toml_file)
|
34
16
|
return toml_to_dict(str_toml)
|
35
17
|
|
36
|
-
|
37
18
|
def toml_to_dict(str_toml):
|
38
19
|
if sys.version_info >= (3, 11):
|
39
20
|
import tomllib
|
osbot_utils/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
v2.
|
1
|
+
v2.79.0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: osbot_utils
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.79.0
|
4
4
|
Summary: OWASP Security Bot - Utils
|
5
5
|
License: MIT
|
6
6
|
Author: Dinis Cruz
|
@@ -21,7 +21,7 @@ Description-Content-Type: text/markdown
|
|
21
21
|
|
22
22
|
# OSBot-Utils
|
23
23
|
|
24
|
-

|
25
25
|

|
26
26
|

|
27
27
|

|
@@ -33,7 +33,7 @@ osbot_utils/fluent/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVG
|
|
33
33
|
osbot_utils/helpers/CFormat.py,sha256=QviXlx3cQF7Wq6bNQmvWPHknDDMQXg5bh5dsRncrg-U,6805
|
34
34
|
osbot_utils/helpers/CPrint.py,sha256=8iCkLaPozi3anzLQ-kPfJTtfLZdOrgpGNJs5UNjGJ9g,1346
|
35
35
|
osbot_utils/helpers/Dependency_Manager.py,sha256=79YRYnVfchewq8iSMJ5dzwW2D5u8chWcIqYE-G9YrSo,1337
|
36
|
-
osbot_utils/helpers/Dict_To_Attr.py,sha256=
|
36
|
+
osbot_utils/helpers/Dict_To_Attr.py,sha256=OWAChOCTM03ECfL4ME7Y0026ZnfA7OmSTIWYKlW9Jmg,139
|
37
37
|
osbot_utils/helpers/Hashicorp_Secrets.py,sha256=e2fWWHK6bubpAm1sw5y8X5kh2Hk5d4JyZCnUovZip5A,4232
|
38
38
|
osbot_utils/helpers/Local_Cache.py,sha256=67qmeVXUBhfqLUQhjFBE9Pjt5dcjpQYhqCTGQNWgVSU,3232
|
39
39
|
osbot_utils/helpers/Local_Caches.py,sha256=LUeNJX07Ccnp1SIhYvhqqQFVF6r_Ez7bWha8ssomuvY,1957
|
@@ -306,6 +306,7 @@ osbot_utils/helpers/trace/Trace_Call__Stats.py,sha256=gmiotIrOXe2ssxodzQQ56t8eGT
|
|
306
306
|
osbot_utils/helpers/trace/Trace_Call__View_Model.py,sha256=a40nn6agCEMd2ecsJ93n8vXij0omh0D69QilqwmN_ao,4545
|
307
307
|
osbot_utils/helpers/trace/Trace_Files.py,sha256=SNpAmuBlSUS9NyVocgZ5vevzqVaIqoh622yZge3a53A,978
|
308
308
|
osbot_utils/helpers/trace/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
309
|
+
osbot_utils/helpers/transformers/Dict__To__Toml.py,sha256=x_5_9xwS6ytSVzpr74AJOjYTnrkTCLPb8MoHyRkWuvA,10791
|
309
310
|
osbot_utils/helpers/xml/Xml__Attribute.py,sha256=_dIVyp0WHfdv306vAj5bpEtiqKa83MLKRH925rjKa94,145
|
310
311
|
osbot_utils/helpers/xml/Xml__Element.py,sha256=NLRdiTsRhqRf0I0ScAdN-tHuSh2qNuKP_tldx7iiSv4,868
|
311
312
|
osbot_utils/helpers/xml/Xml__File.py,sha256=ECR4WD57ePyA88uioKVt5GVbWXddM_Y1OsWAJNzAg74,420
|
@@ -416,7 +417,7 @@ osbot_utils/type_safe/type_safe_core/collections/Type_Safe__Tuple.py,sha256=Kx7C
|
|
416
417
|
osbot_utils/type_safe/type_safe_core/collections/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
417
418
|
osbot_utils/type_safe/type_safe_core/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
418
419
|
osbot_utils/type_safe/type_safe_core/decorators/type_safe.py,sha256=wOTMvZBl5hWMz-HuIRZpPBGN0oSbXWd9wH5xxZkfLlA,1796
|
419
|
-
osbot_utils/type_safe/type_safe_core/methods/Type_Safe__Method.py,sha256
|
420
|
+
osbot_utils/type_safe/type_safe_core/methods/Type_Safe__Method.py,sha256=-EHM5goVg-CvVufeMFi_jUSTldpla4FQiq6XO5ZJtUs,18776
|
420
421
|
osbot_utils/type_safe/type_safe_core/methods/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
421
422
|
osbot_utils/type_safe/type_safe_core/methods/type_safe_property.py,sha256=DcJkOIs6swJtkglsZVKLyFSczCGSJISOVwAmvjCOQvo,1425
|
422
423
|
osbot_utils/type_safe/type_safe_core/shared/Type_Safe__Annotations.py,sha256=kabSiRPYPjpMBJxfjDB5AFRTx-hX17tOznZAd_qQID4,1147
|
@@ -464,12 +465,12 @@ osbot_utils/utils/Regex.py,sha256=MtHhk69ax7Nwu4CQZK7y4KXHZ6VREwEpIchuioB168c,96
|
|
464
465
|
osbot_utils/utils/Status.py,sha256=OjqLwUhHqY-j-JeRN-hIaVZQHPRdyjR7y6i6ujsB-Yc,4287
|
465
466
|
osbot_utils/utils/Str.py,sha256=KQVfh0o3BxJKVm24yhAhgIGH5QYfzpP1G-siVv2zQws,3301
|
466
467
|
osbot_utils/utils/Threads.py,sha256=YI1T382AtJpHVsa-BK7SycmEYhnkqHIiYyK_5HSmUtw,4329
|
467
|
-
osbot_utils/utils/Toml.py,sha256=
|
468
|
+
osbot_utils/utils/Toml.py,sha256=grjWkVPIMVkawJ499FVIJKxQp8FJ2wcsd0Z3YIR4drM,1148
|
468
469
|
osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
|
469
470
|
osbot_utils/utils/Zip.py,sha256=mG42lgTY0tnm14T3P1-DSAIZKkTiYoO3odZ1aOUdc1I,14394
|
470
471
|
osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
471
|
-
osbot_utils/version,sha256=
|
472
|
-
osbot_utils-2.
|
473
|
-
osbot_utils-2.
|
474
|
-
osbot_utils-2.
|
475
|
-
osbot_utils-2.
|
472
|
+
osbot_utils/version,sha256=LBnSHfeuqdNUDCaJ0l1-HSUQy_-YezgRfKFIWsPg7Q4,8
|
473
|
+
osbot_utils-2.79.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
474
|
+
osbot_utils-2.79.0.dist-info/METADATA,sha256=EYa9xfe3-uAcOGHcGHDaX0LIrRtztORvnB_PJ8cS-G0,7918
|
475
|
+
osbot_utils-2.79.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
476
|
+
osbot_utils-2.79.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|