osbot-utils 2.75.0__py3-none-any.whl → 2.77.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 (34) hide show
  1. osbot_utils/helpers/ast/Ast_Load.py +5 -5
  2. osbot_utils/helpers/html/{Tag__Base.py → tags/Tag__Base.py} +1 -1
  3. osbot_utils/helpers/html/tags/Tag__Body.py +5 -0
  4. osbot_utils/helpers/html/tags/Tag__Div.py +5 -0
  5. osbot_utils/helpers/html/{Tag__H.py → tags/Tag__H.py} +1 -1
  6. osbot_utils/helpers/html/tags/Tag__HR.py +5 -0
  7. osbot_utils/helpers/html/{Tag__Head.py → tags/Tag__Head.py} +3 -3
  8. osbot_utils/helpers/html/{Tag__Html.py → tags/Tag__Html.py} +3 -3
  9. osbot_utils/helpers/html/{Tag__Link.py → tags/Tag__Link.py} +1 -1
  10. osbot_utils/helpers/html/{Tag__Style.py → tags/Tag__Style.py} +2 -2
  11. osbot_utils/helpers/html/{Tag__Text.py → tags/Tag__Text.py} +1 -1
  12. osbot_utils/helpers/html/tags/__init__.py +0 -0
  13. osbot_utils/helpers/html/{Html_Dict__To__Html.py → transformers/Html_Dict__To__Html.py} +1 -1
  14. osbot_utils/helpers/html/{Html_Dict__To__Html_Document.py → transformers/Html_Dict__To__Html_Document.py} +1 -1
  15. osbot_utils/helpers/html/{Html_Dict__To__Html_Tags.py → transformers/Html_Dict__To__Html_Tags.py} +8 -8
  16. osbot_utils/helpers/html/{Html_Document__To__Html_Dict.py → transformers/Html_Document__To__Html_Dict.py} +1 -1
  17. osbot_utils/helpers/html/{Html__To__Html_Document.py → transformers/Html__To__Html_Document.py} +4 -4
  18. osbot_utils/helpers/html/{Html__To__Html_Tag.py → transformers/Html__To__Html_Tag.py} +2 -2
  19. osbot_utils/helpers/html/transformers/__init__.py +0 -0
  20. osbot_utils/helpers/html/utils/Html__Query.py +226 -0
  21. osbot_utils/helpers/html/utils/__init__.py +0 -0
  22. osbot_utils/testing/test_data/__init__.py +0 -0
  23. osbot_utils/testing/test_data/const__test__data__html.py +45 -0
  24. osbot_utils/type_safe/type_safe_core/steps/Type_Safe__Step__Class_Kwargs.py +30 -6
  25. osbot_utils/version +1 -1
  26. {osbot_utils-2.75.0.dist-info → osbot_utils-2.77.0.dist-info}/METADATA +3 -3
  27. {osbot_utils-2.75.0.dist-info → osbot_utils-2.77.0.dist-info}/RECORD +31 -25
  28. osbot_utils/helpers/html/Tag__Body.py +0 -5
  29. osbot_utils/helpers/html/Tag__Div.py +0 -5
  30. osbot_utils/helpers/html/Tag__HR.py +0 -5
  31. /osbot_utils/helpers/html/{CSS_Dict__To__Css.py → transformers/CSS_Dict__To__Css.py} +0 -0
  32. /osbot_utils/helpers/html/{Html__To__Html_Dict.py → transformers/Html__To__Html_Dict.py} +0 -0
  33. {osbot_utils-2.75.0.dist-info → osbot_utils-2.77.0.dist-info}/LICENSE +0 -0
  34. {osbot_utils-2.75.0.dist-info → osbot_utils-2.77.0.dist-info}/WHEEL +0 -0
@@ -1,11 +1,11 @@
1
1
  import ast
2
2
 
3
- from osbot_utils.helpers.Type_Registry import type_registry
4
- from osbot_utils.utils.Files import file_contents, file_exists
5
- from osbot_utils.utils.Functions import python_file
6
- from osbot_utils.helpers.ast.Ast_Node import Ast_Node
3
+ from osbot_utils.helpers.Type_Registry import type_registry
4
+ from osbot_utils.utils.Files import file_contents, file_exists
5
+ from osbot_utils.utils.Functions import python_file
6
+ from osbot_utils.helpers.ast.Ast_Node import Ast_Node
7
7
 
8
- #todo: check if this is stll needed since it Ast_Visit does it similar
8
+ #todo: check if this is still needed since it Ast_Visit does it similar
9
9
  class Ast_Load(ast.NodeVisitor):
10
10
 
11
11
  def __init__(self):
@@ -1,6 +1,6 @@
1
1
  from collections import defaultdict
2
2
 
3
- from osbot_utils.helpers.html.Html__To__Html_Dict import STRING__SCHEMA_TEXT
3
+ from osbot_utils.helpers.html.transformers.Html__To__Html_Dict import STRING__SCHEMA_TEXT
4
4
  from osbot_utils.type_safe.Type_Safe import Type_Safe
5
5
  from osbot_utils.utils.Files import file_create
6
6
 
@@ -0,0 +1,5 @@
1
+ from osbot_utils.helpers.html.tags.Tag__Base import Tag__Base
2
+
3
+
4
+ class Tag__Body(Tag__Base):
5
+ tag_name = 'body'
@@ -0,0 +1,5 @@
1
+ from osbot_utils.helpers.html.tags.Tag__Base import Tag__Base
2
+
3
+
4
+ class Tag__Div(Tag__Base):
5
+ tag_name = 'div'
@@ -1,4 +1,4 @@
1
- from osbot_utils.helpers.html.Tag__Base import Tag__Base
1
+ from osbot_utils.helpers.html.tags.Tag__Base import Tag__Base
2
2
 
3
3
 
4
4
  class Tag__H(Tag__Base):
@@ -0,0 +1,5 @@
1
+ from osbot_utils.helpers.html.tags.Tag__Base import Tag__Base
2
+
3
+
4
+ class Tag__HR(Tag__Base):
5
+ tag_name = 'hr'
@@ -1,8 +1,8 @@
1
1
  from typing import List
2
2
 
3
- from osbot_utils.helpers.html.Tag__Base import Tag__Base
4
- from osbot_utils.helpers.html.Tag__Link import Tag__Link
5
- from osbot_utils.helpers.html.Tag__Style import Tag__Style
3
+ from osbot_utils.helpers.html.tags.Tag__Base import Tag__Base
4
+ from osbot_utils.helpers.html.tags.Tag__Link import Tag__Link
5
+ from osbot_utils.helpers.html.tags.Tag__Style import Tag__Style
6
6
  from osbot_utils.utils.Dev import pprint
7
7
 
8
8
 
@@ -1,6 +1,6 @@
1
- from osbot_utils.helpers.html.Tag__Base import Tag__Base
2
- from osbot_utils.helpers.html.Tag__Body import Tag__Body
3
- from osbot_utils.helpers.html.Tag__Head import Tag__Head
1
+ from osbot_utils.helpers.html.tags.Tag__Base import Tag__Base
2
+ from osbot_utils.helpers.html.tags.Tag__Body import Tag__Body
3
+ from osbot_utils.helpers.html.tags.Tag__Head import Tag__Head
4
4
  from osbot_utils.utils.Misc import str_to_bytes
5
5
 
6
6
  ATTRIBUTES_NAMES__LINK = ['lang']
@@ -1,4 +1,4 @@
1
- from osbot_utils.helpers.html.Tag__Base import Tag__Base
1
+ from osbot_utils.helpers.html.tags.Tag__Base import Tag__Base
2
2
 
3
3
  ATTRIBUTES_NAMES__LINK = ['href', 'rel', 'integrity', 'crossorigin']
4
4
 
@@ -1,5 +1,5 @@
1
- from osbot_utils.helpers.html.CSS_Dict__To__Css import CSS_Dict__To__Css
2
- from osbot_utils.helpers.html.Tag__Base import Tag__Base, INDENT_SIZE
1
+ from osbot_utils.helpers.html.transformers.CSS_Dict__To__Css import CSS_Dict__To__Css
2
+ from osbot_utils.helpers.html.tags.Tag__Base import Tag__Base, INDENT_SIZE
3
3
 
4
4
 
5
5
  class Tag__Style(Tag__Base):
@@ -1,4 +1,4 @@
1
- from osbot_utils.helpers.html.Html__To__Html_Dict import STRING__SCHEMA_TEXT
1
+ from osbot_utils.helpers.html.transformers.Html__To__Html_Dict import STRING__SCHEMA_TEXT
2
2
 
3
3
 
4
4
  class Tag__Text:
File without changes
@@ -1,4 +1,4 @@
1
- from osbot_utils.helpers.html.Html__To__Html_Dict import STRING__SCHEMA_TEXT, STRING__SCHEMA_NODES
1
+ from osbot_utils.helpers.html.transformers.Html__To__Html_Dict import STRING__SCHEMA_TEXT, STRING__SCHEMA_NODES
2
2
 
3
3
  HTML_SELF_CLOSING_TAGS = {'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta',
4
4
  'param', 'source', 'track', 'wbr'}
@@ -1,5 +1,5 @@
1
1
  from typing import Dict, Any
2
- from osbot_utils.helpers.html.Html__To__Html_Dict import STRING__SCHEMA_TEXT, STRING__SCHEMA_NODES
2
+ from osbot_utils.helpers.html.transformers.Html__To__Html_Dict import STRING__SCHEMA_TEXT, STRING__SCHEMA_NODES
3
3
  from osbot_utils.helpers.html.schemas.Schema__Html_Document import Schema__Html_Document
4
4
  from osbot_utils.helpers.html.schemas.Schema__Html_Node import Schema__Html_Node
5
5
  from osbot_utils.helpers.html.schemas.Schema__Html_Node__Data import Schema__Html_Node__Data
@@ -1,11 +1,11 @@
1
- from osbot_utils.helpers.html.Html_Dict__To__Html import HTML_SELF_CLOSING_TAGS
2
- from osbot_utils.helpers.html.Html__To__Html_Dict import STRING__SCHEMA_TEXT, STRING__SCHEMA_NODES
3
- from osbot_utils.helpers.html.Tag__Base import Tag__Base
4
- from osbot_utils.helpers.html.Tag__Body import Tag__Body
5
- from osbot_utils.helpers.html.Tag__Head import Tag__Head
6
- from osbot_utils.helpers.html.Tag__Html import Tag__Html
7
- from osbot_utils.helpers.html.Tag__Link import Tag__Link
8
- from osbot_utils.helpers.html.Tag__Text import Tag__Text
1
+ from osbot_utils.helpers.html.transformers.Html_Dict__To__Html import HTML_SELF_CLOSING_TAGS
2
+ from osbot_utils.helpers.html.transformers.Html__To__Html_Dict import STRING__SCHEMA_TEXT, STRING__SCHEMA_NODES
3
+ from osbot_utils.helpers.html.tags.Tag__Base import Tag__Base
4
+ from osbot_utils.helpers.html.tags.Tag__Body import Tag__Body
5
+ from osbot_utils.helpers.html.tags.Tag__Head import Tag__Head
6
+ from osbot_utils.helpers.html.tags.Tag__Html import Tag__Html
7
+ from osbot_utils.helpers.html.tags.Tag__Link import Tag__Link
8
+ from osbot_utils.helpers.html.tags.Tag__Text import Tag__Text
9
9
 
10
10
 
11
11
  class Html_Dict__To__Html_Tags:
@@ -1,5 +1,5 @@
1
1
  from typing import Dict, Any, List, Union
2
- from osbot_utils.helpers.html.Html__To__Html_Dict import STRING__SCHEMA_TEXT, STRING__SCHEMA_NODES, STRING__SCHEMA_TAG, STRING__SCHEMA_ATTRS
2
+ from osbot_utils.helpers.html.transformers.Html__To__Html_Dict import STRING__SCHEMA_TEXT, STRING__SCHEMA_NODES, STRING__SCHEMA_TAG, STRING__SCHEMA_ATTRS
3
3
  from osbot_utils.helpers.html.schemas.Schema__Html_Document import Schema__Html_Document
4
4
  from osbot_utils.helpers.html.schemas.Schema__Html_Node import Schema__Html_Node
5
5
  from osbot_utils.type_safe.Type_Safe import Type_Safe
@@ -1,7 +1,7 @@
1
- from osbot_utils.helpers.html.Html_Dict__To__Html_Document import Html_Dict__To__Html_Document
2
- from osbot_utils.helpers.html.Html__To__Html_Dict import Html__To__Html_Dict
3
- from osbot_utils.helpers.html.schemas.Schema__Html_Document import Schema__Html_Document
4
- from osbot_utils.type_safe.Type_Safe import Type_Safe
1
+ from osbot_utils.helpers.html.transformers.Html_Dict__To__Html_Document import Html_Dict__To__Html_Document
2
+ from osbot_utils.helpers.html.transformers.Html__To__Html_Dict import Html__To__Html_Dict
3
+ from osbot_utils.helpers.html.schemas.Schema__Html_Document import Schema__Html_Document
4
+ from osbot_utils.type_safe.Type_Safe import Type_Safe
5
5
 
6
6
  class Html__To__Html_Document(Type_Safe):
7
7
  html: str
@@ -1,5 +1,5 @@
1
- from osbot_utils.helpers.html.Html_Dict__To__Html_Tags import Html_Dict__To__Html_Tags
2
- from osbot_utils.helpers.html.Html__To__Html_Dict import Html__To__Html_Dict
1
+ from osbot_utils.helpers.html.transformers.Html_Dict__To__Html_Tags import Html_Dict__To__Html_Tags
2
+ from osbot_utils.helpers.html.transformers.Html__To__Html_Dict import Html__To__Html_Dict
3
3
 
4
4
 
5
5
  class Html__To__Html_Tag:
File without changes
@@ -0,0 +1,226 @@
1
+ from typing import List, Optional, Dict, Any
2
+ from osbot_utils.helpers.html.transformers.Html__To__Html_Document import Html__To__Html_Document
3
+ from osbot_utils.helpers.html.schemas.Schema__Html_Document import Schema__Html_Document
4
+ from osbot_utils.helpers.html.schemas.Schema__Html_Node import Schema__Html_Node
5
+ from osbot_utils.type_safe.Type_Safe import Type_Safe
6
+
7
+
8
+ class Html__Query(Type_Safe):
9
+ html : str
10
+ document : Schema__Html_Document
11
+
12
+ def __enter__(self):
13
+ self.document = Html__To__Html_Document(html=self.html).convert()
14
+ return self
15
+
16
+ def __exit__(self, exc_type, exc_val, exc_tb):
17
+ pass
18
+
19
+ @property
20
+ def root(self) -> Schema__Html_Node: # Get the root node
21
+ return self.document.root_node
22
+
23
+ @property
24
+ def head(self) -> Optional[Schema__Html_Node]: # Get the head node
25
+ return self.find_child_by_tag(self.root, 'head')
26
+
27
+ @property
28
+ def body(self) -> Optional[Schema__Html_Node]: # Get the body node
29
+ return self.find_child_by_tag(self.root, 'body')
30
+
31
+ @property
32
+ def title(self) -> Optional[str]: # Get the page title text
33
+ if not self.head:
34
+ return None
35
+ title_node = self.find_child_by_tag(self.head, 'title')
36
+ if title_node:
37
+ return self.get_text_content(title_node).strip()
38
+ return None
39
+
40
+ @property
41
+ def links(self) -> List[Dict[str, str]]: # Get all link tags as list of attribute dicts
42
+ if not self.head:
43
+ return []
44
+ return [node.attrs for node in self.head.child_nodes if node.tag == 'link']
45
+
46
+ @property
47
+ def link_hrefs(self) -> List[str]: # Get all link hrefs
48
+ return [link.get('href', '') for link in self.links if 'href' in link]
49
+
50
+ @property
51
+ def css_links(self) -> List[str]: # Get all stylesheet link hrefs
52
+ result = []
53
+ for link in self.links:
54
+ if link.get('rel') == 'stylesheet' and 'href' in link:
55
+ result.append(link['href'])
56
+ return result
57
+
58
+ @property
59
+ def script_sources(self) -> List[str]: # Get all external script src URLs
60
+ scripts = self.find_all_by_tag('script')
61
+ return [s.attrs.get('src') for s in scripts if 'src' in s.attrs]
62
+
63
+ @property
64
+ def inline_scripts(self) -> List[str]: # Get all inline script contents
65
+ scripts = self.find_all_by_tag('script')
66
+ result = []
67
+ for script in scripts:
68
+ if 'src' not in script.attrs: # Only inline scripts
69
+ content = self.get_text_content(script)
70
+ if content:
71
+ result.append(content)
72
+ return result
73
+
74
+ @property
75
+ def meta_tags(self) -> List[Dict[str, str]]: # Get all meta tags as list of attribute dicts
76
+ if not self.head:
77
+ return []
78
+ return [node.attrs for node in self.head.child_nodes if node.tag == 'meta']
79
+
80
+ @property
81
+ def favicon(self) -> Optional[str]: # Get favicon URL if present
82
+ return (self.find_link_by_rel('shortcut icon') or
83
+ self.find_link_by_rel('icon'))
84
+
85
+ @property
86
+ def stylesheets(self) -> List[str]: # Alias for css_links
87
+ return self.css_links
88
+
89
+ # Query methods
90
+ def has_link(self, href : str = None , # Check if link exists with attributes
91
+ rel : str = None ,
92
+ **attrs
93
+ ) -> bool:
94
+ for link in self.links:
95
+ if href and link.get('href') != href:
96
+ continue
97
+ if rel and link.get('rel') != rel:
98
+ continue
99
+ if all(link.get(k) == v for k, v in attrs.items()): # Check any additional attributes
100
+ return True
101
+ return False
102
+
103
+ def has_script(self, src : str = None , # Check if script exists with src or text
104
+ contains : str = None
105
+ ) -> bool:
106
+ scripts = self.find_all_by_tag('script')
107
+ for script in scripts:
108
+ if src and script.attrs.get('src') == src:
109
+ return True
110
+ if contains:
111
+ content = self.get_text_content(script)
112
+ if contains in content:
113
+ return True
114
+ return False
115
+
116
+ def has_meta(self, name : str = None , # Check if meta tag exists with attributes
117
+ content : str = None ,
118
+ **attrs
119
+ ) -> bool:
120
+ for meta in self.meta_tags:
121
+ if name and meta.get('name') != name:
122
+ continue
123
+ if content and meta.get('content') != content:
124
+ continue
125
+ if all(meta.get(k) == v for k, v in attrs.items()):
126
+ return True
127
+ return False
128
+
129
+ def find_by_id(self, element_id : str # Find element by id attribute
130
+ ) -> Optional[Schema__Html_Node]:
131
+ return self.find_by_attribute('id', element_id)
132
+
133
+ def find_by_class(self, class_name : str # Find all elements with a specific class
134
+ ) -> List[Schema__Html_Node]:
135
+ result = []
136
+ for node in self.find_all():
137
+ classes = node.attrs.get('class', '').split()
138
+ if class_name in classes:
139
+ result.append(node)
140
+ return result
141
+
142
+ def find_by_tag(self, tag_name : str # Find all elements with a specific tag
143
+ ) -> List[Schema__Html_Node]:
144
+ return self.find_all_by_tag(tag_name)
145
+
146
+ def get_attribute(self, element : Schema__Html_Node , # Get attribute value from an element
147
+ attr_name : str
148
+ ) -> Optional[str]:
149
+ return element.attrs.get(attr_name)
150
+
151
+ def get_text(self, element : Optional[Schema__Html_Node] = None # Get text content of element or document
152
+ ) -> str:
153
+ if element is None:
154
+ element = self.root
155
+ return self.get_text_content(element)
156
+
157
+
158
+ # other helper methods
159
+ def find_child_by_tag(self, parent : Schema__Html_Node, # Find first direct child with tag
160
+ tag : str
161
+ ) -> Optional[Schema__Html_Node]:
162
+ for child in parent.child_nodes:
163
+ if child.tag == tag:
164
+ return child
165
+ return None
166
+
167
+ def find_all_by_tag(self, tag : str, # Recursively find all nodes with tag
168
+ node : Optional[Schema__Html_Node] = None
169
+ ) -> List[Schema__Html_Node]:
170
+ if node is None:
171
+ node = self.root
172
+
173
+ result = []
174
+ if node.tag == tag:
175
+ result.append(node)
176
+
177
+ for child in node.child_nodes:
178
+ result.extend(self.find_all_by_tag(tag, child))
179
+
180
+ return result
181
+
182
+ def find_by_attribute(self, attr_name : str , # Find first node with attribute value
183
+ attr_value : str ,
184
+ node : Optional[Schema__Html_Node] = None
185
+ ) -> Optional[Schema__Html_Node]:
186
+ if node is None:
187
+ node = self.root
188
+
189
+ if node.attrs.get(attr_name) == attr_value:
190
+ return node
191
+
192
+ for child in node.child_nodes:
193
+ result = self.find_by_attribute(attr_name, attr_value, child)
194
+ if result:
195
+ return result
196
+
197
+ return None
198
+
199
+ def find_all(self, node : Optional[Schema__Html_Node] = None # Get all nodes in the tree
200
+ ) -> List[Schema__Html_Node]:
201
+ if node is None:
202
+ node = self.root
203
+
204
+ result = [node]
205
+ for child in node.child_nodes:
206
+ result.extend(self.find_all(child))
207
+
208
+ return result
209
+
210
+ def find_link_by_rel(self, rel_value: str) -> Optional[str]:
211
+ for link in self.links:
212
+ if link.get('rel') == rel_value:
213
+ return link.get('href')
214
+ return None
215
+
216
+ def get_text_content(self, node : Schema__Html_Node # Get all text content from node
217
+ ) -> str:
218
+ texts = []
219
+
220
+ for text_node in node.text_nodes: # Get text from this node's text_nodes
221
+ texts.append(text_node.data)
222
+
223
+ for child in node.child_nodes: # Recursively get text from children
224
+ texts.append(self.get_text_content(child))
225
+
226
+ return ''.join(texts)
File without changes
File without changes
@@ -0,0 +1,45 @@
1
+ TEST__DATA__HTML__SIMPLE = """
2
+ <html>
3
+ <head>
4
+ <title>Test Page</title>
5
+ <link rel="stylesheet" href="/css/main.css">
6
+ <link rel="shortcut icon" href="/favicon.ico">
7
+ <meta name="description" content="Test description">
8
+ </head>
9
+ <body>
10
+ <div id="main">Content</div>
11
+ <script src="/js/app.js"></script>
12
+ <script>console.log('inline');</script>
13
+ </body>
14
+ </html>
15
+ """
16
+ TEST__DATA__HTML__SWAGGER = """
17
+ <!DOCTYPE html>
18
+ <html>
19
+ <head>
20
+ <link type="text/css" rel="stylesheet" href="/static/swagger-ui/swagger-ui.css">
21
+ <link rel="shortcut icon" href="/static/swagger-ui/favicon.png">
22
+ <title>Fast_API - Swagger UI</title>
23
+ </head>
24
+ <body>
25
+ <div id="swagger-ui"></div>
26
+ <script src="/static/swagger-ui/swagger-ui-bundle.js"></script>
27
+ <script>
28
+ const ui = SwaggerUIBundle({
29
+ url: '/openapi.json',
30
+ "dom_id": "#swagger-ui"
31
+ })
32
+ </script>
33
+ </body>
34
+ </html>
35
+ """
36
+
37
+ TEST__DATA__HTML__MIXED_CONTENT = """
38
+ <div class="container">
39
+ Text before
40
+ <p class="paragraph">Paragraph content</p>
41
+ Text middle
42
+ <span class="highlight">Highlighted</span>
43
+ Text after
44
+ </div>
45
+ """
@@ -65,15 +65,39 @@ class Type_Safe__Step__Class_Kwargs:
65
65
  var_name : str ,
66
66
  var_type : Type )\
67
67
  -> None:
68
- var_value = getattr(base_cls, var_name) # Get current value
69
- if var_value is None: # Allow None assignments
68
+ # var_value = getattr(base_cls, var_name) # Get current value
69
+ # if var_value is None: # Allow None assignments
70
+ # return
71
+ #
72
+ # if type_safe_validation.should_skip_type_check(var_type): # Skip validation if needed
73
+ # return
74
+ #
75
+ # type_safe_validation.validate_variable_type (var_name, var_type, var_value) # Validate type
76
+ # type_safe_validation.validate_type_immutability(var_name, var_type) # Validate immutability
77
+
78
+ var_value = getattr(base_cls, var_name)
79
+ if var_value is None:
70
80
  return
71
-
72
- if type_safe_validation.should_skip_type_check(var_type): # Skip validation if needed
81
+ if type_safe_validation.should_skip_type_check(var_type):
73
82
  return
74
83
 
75
- type_safe_validation.validate_variable_type (var_name, var_type, var_value) # Validate type
76
- type_safe_validation.validate_type_immutability(var_name, var_type) # Validate immutability
84
+ # NEW: Try to convert primitive values to Type_Safe__Primitive types
85
+ from osbot_utils.type_safe.Type_Safe__Primitive import Type_Safe__Primitive
86
+ if (isinstance(var_type, type) and
87
+ issubclass(var_type, Type_Safe__Primitive) and
88
+ type(var_value) in (str, int, float)):
89
+ try:
90
+ # Attempt conversion and validate the converted value
91
+ converted_value = var_type(var_value)
92
+ # Set the converted value back on the class
93
+ setattr(base_cls, var_name, converted_value)
94
+ var_value = converted_value
95
+ except (ValueError, TypeError):
96
+ # If conversion fails, let the original validation handle it
97
+ pass
98
+
99
+ type_safe_validation.validate_variable_type(var_name, var_type, var_value)
100
+ type_safe_validation.validate_type_immutability(var_name, var_type)
77
101
 
78
102
  def process_annotation(self, cls : Type , # Process single annotation
79
103
  base_cls : Type ,
osbot_utils/version CHANGED
@@ -1 +1 @@
1
- v2.75.0
1
+ v2.77.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: osbot_utils
3
- Version: 2.75.0
3
+ Version: 2.77.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
- ![Current Release](https://img.shields.io/badge/release-v2.75.0-blue)
24
+ ![Current Release](https://img.shields.io/badge/release-v2.77.0-blue)
25
25
  ![Python](https://img.shields.io/badge/python-3.8+-green)
26
26
  ![Type-Safe](https://img.shields.io/badge/Type--Safe-✓-brightgreen)
27
27
  ![Caching](https://img.shields.io/badge/Caching-Built--In-orange)
@@ -93,7 +93,7 @@ fetcher.fetch(10) # Returns cached result
93
93
  ### HTML Parsing
94
94
 
95
95
  ```python
96
- from osbot_utils.helpers.html.Html__To__Html_Dict import html_to_dict
96
+ from osbot_utils.helpers.html.transformers.Html__To__Html_Dict import html_to_dict
97
97
 
98
98
  html_code = "<html><body><h1>Hello</h1></body></html>"
99
99
  print(html_to_dict(html_code))
@@ -48,7 +48,7 @@ osbot_utils/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
48
48
  osbot_utils/helpers/ast/Ast.py,sha256=lcPQOSxXI6zgmMnIVF9WM6ISqViWX-sq4d_UC0CDG8s,1155
49
49
  osbot_utils/helpers/ast/Ast_Base.py,sha256=x3UGJsxkIkMlkzt59eZYZG9NmvvODO5jaRBEeiqSaSA,3740
50
50
  osbot_utils/helpers/ast/Ast_Data.py,sha256=EL-6lkNDMe_BKBwFP1sJW-Y8t6TXYYv0uGdlxix4Tyg,697
51
- osbot_utils/helpers/ast/Ast_Load.py,sha256=ZO2QjhQ13j1m4MwAVbbdAoQ4UoUfzuU6E_RobkhZVpI,2100
51
+ osbot_utils/helpers/ast/Ast_Load.py,sha256=qiFe_PC5I7ncvSl8kWHTKuc8IxDpmCZ_UznQLWpiYSk,2122
52
52
  osbot_utils/helpers/ast/Ast_Merge.py,sha256=An_u2E906DrMlAl83VyTNLKBSc0uEm25RWLRZsci2rk,848
53
53
  osbot_utils/helpers/ast/Ast_Node.py,sha256=S4WUSRLHqVn3dJOkv1C0xVUN9sDx7sjkMXcbPJxaA4U,5761
54
54
  osbot_utils/helpers/ast/Ast_Visit.py,sha256=vdBtFMt4Ogax2BbyoJNQC_4FqHp81N9Oh1Afsq6xkXU,2875
@@ -175,30 +175,34 @@ osbot_utils/helpers/generators/Generator_Manager.py,sha256=N6HSGuPn7lOGAqQL1a5Vg
175
175
  osbot_utils/helpers/generators/Model__Generator_State.py,sha256=cS9tigdBIAvexip2VC8B0meegslzlu-cOosTDiEpe54,903
176
176
  osbot_utils/helpers/generators/Model__Generator_Target.py,sha256=Iz4bR4iRneH7lv9ul0xc_p52djTR0moR1SdyC3dUZxI,850
177
177
  osbot_utils/helpers/generators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
178
- osbot_utils/helpers/html/CSS_Dict__To__Css.py,sha256=ZDIVfFCYO4UQsRprbx9vCosFqrnHizZUH-JgP5oZcuA,1102
179
- osbot_utils/helpers/html/Html_Dict__To__Html.py,sha256=Xa5J1elZBK1a5ae75ckenTtNOZs1XX87s1qmu73JatE,4547
180
- osbot_utils/helpers/html/Html_Dict__To__Html_Document.py,sha256=mUi3U5zJwFC7iXQ-kT8uWhMkkK9ZIUKHukdSOuIBCfc,3132
181
- osbot_utils/helpers/html/Html_Dict__To__Html_Tags.py,sha256=46-5aeCnx5LgegKpN227xtx21WcQOB_7gN9NCcxYoA0,7019
182
- osbot_utils/helpers/html/Html_Document__To__Html_Dict.py,sha256=D4tiZaPpyUXKsNURejvBXNW3BFX3dQAm65bLBkD0FhY,2509
183
- osbot_utils/helpers/html/Html__To__Html_Dict.py,sha256=GJ4NZZ5lMFr2u0hfTpqPOMXmKLyinjCeqypg3JjME8c,4405
184
- osbot_utils/helpers/html/Html__To__Html_Document.py,sha256=xVbIT3TaxZPt4cz3lO4WvSru7FyWI1p36qdXp6HGC8o,886
185
- osbot_utils/helpers/html/Html__To__Html_Tag.py,sha256=Qz6he08DwfYkYM_krt_FCVtEWgw6_9bs5j5CoC1FCQQ,566
186
- osbot_utils/helpers/html/Tag__Base.py,sha256=geD7TpA3lHrSiaoLsViH2rcjrqZkMxNpDOhLx3HYbSk,4470
187
- osbot_utils/helpers/html/Tag__Body.py,sha256=U3UNVs1mNBsJ_kG_-OtwYPi-YzFb4Y2w4vIsvAn0W3g,109
188
- osbot_utils/helpers/html/Tag__Div.py,sha256=so47ldnc8nDGZAlZWp2BtfDxdhwzmKjCW8ca2MUbPDE,109
189
- osbot_utils/helpers/html/Tag__H.py,sha256=Z6PD5Uf5wlXmY7-7Xi5bv3Z_EykqxH4wt1Y_U2Sg5HY,295
190
- osbot_utils/helpers/html/Tag__HR.py,sha256=Z9YkBbKxas1Q4Tuw_xdpn3FQmkwAPCippilqCgXFhxA,107
191
- osbot_utils/helpers/html/Tag__Head.py,sha256=uMuxtfkLkxgTMFVUPIWxvu1VwMyGkE7AXylDZJJHElg,1127
192
- osbot_utils/helpers/html/Tag__Html.py,sha256=6vVIy0LLTseyj7cdLYHh6Pq8otfc90CxmCL3EGeCRhY,1143
193
- osbot_utils/helpers/html/Tag__Link.py,sha256=rQ-gZN8EkSv5x1S-smdjvFflwMQHACHQXiOdx0MFke8,437
194
- osbot_utils/helpers/html/Tag__Style.py,sha256=wRZ8DN1HVCtrnL4Flz82oByqJOy8Th40EhYCrZsuk2c,872
195
- osbot_utils/helpers/html/Tag__Text.py,sha256=Pqf96QGwX9wdGqlwBvWYHWz9Qqi-oZrkgEzHQm6LzdY,241
196
178
  osbot_utils/helpers/html/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
197
179
  osbot_utils/helpers/html/schemas/Schema__Html_Document.py,sha256=tQJLc0rf2CuG1sGNB04cPyVV7KpCGXYDt0wEnFtWohg,403
198
180
  osbot_utils/helpers/html/schemas/Schema__Html_Node.py,sha256=iMGClwil99_KoeLuft53DQLu9Jw-PCqRjBXpfInd7rM,794
199
181
  osbot_utils/helpers/html/schemas/Schema__Html_Node__Data.py,sha256=GiAZY5mO3DNasUO_oNM4ndTvRU2VpjPxOi7kYzu2DHE,568
200
182
  osbot_utils/helpers/html/schemas/Schema__Html_Node__Data__Type.py,sha256=mbYivcm6BfN5-oeCyl6gjbnSKs_b_t-G2H1rpSK6nUY,90
201
183
  osbot_utils/helpers/html/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
184
+ osbot_utils/helpers/html/tags/Tag__Base.py,sha256=W6zw5Sn4i8bEM6PTUVRlZgOwDRZFRxpaOjVthpJRPn4,4483
185
+ osbot_utils/helpers/html/tags/Tag__Body.py,sha256=BK_VJHMnGl-RpV_6C_C21hThgMVq76r5XtvtKAqFf0c,114
186
+ osbot_utils/helpers/html/tags/Tag__Div.py,sha256=GQUnuf4Yo_Vp3FnHagaIedeRrnT3DoHKwj74oBxLlPg,114
187
+ osbot_utils/helpers/html/tags/Tag__H.py,sha256=6-SUbtChh_uGQ7RGLuEgiYv6f8L-7fGGEXB0XRljey8,300
188
+ osbot_utils/helpers/html/tags/Tag__HR.py,sha256=KOTe7BvhNVquU4w78U4aRixo_IvS8sY0IkPKN3_Udsg,112
189
+ osbot_utils/helpers/html/tags/Tag__Head.py,sha256=A86b-qVAFhUL09dB85XlLkZX9fTlTEE0XIPJ73okLwI,1142
190
+ osbot_utils/helpers/html/tags/Tag__Html.py,sha256=SpO9jhbqUzxZYN-LxzNyWAD2Z1FoGE9Fp76lFH57QJU,1158
191
+ osbot_utils/helpers/html/tags/Tag__Link.py,sha256=ISoaBa0ccxMkQOk4-bt4XhTzjxPzQoLTCxVAgn50wGI,442
192
+ osbot_utils/helpers/html/tags/Tag__Style.py,sha256=q5IoR0VzKnE5R07sk_RpWALwhWyymX0POGYnvCGbTiI,890
193
+ osbot_utils/helpers/html/tags/Tag__Text.py,sha256=jU0hRdckTdIs_kNiZGCKbPKuXhSXFaJIh3gxB-drYqw,254
194
+ osbot_utils/helpers/html/tags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
195
+ osbot_utils/helpers/html/transformers/CSS_Dict__To__Css.py,sha256=ZDIVfFCYO4UQsRprbx9vCosFqrnHizZUH-JgP5oZcuA,1102
196
+ osbot_utils/helpers/html/transformers/Html_Dict__To__Html.py,sha256=zK4AKuxusc_ectbqly4CR1pNcMG74SyqMsocB0vSHjU,4560
197
+ osbot_utils/helpers/html/transformers/Html_Dict__To__Html_Document.py,sha256=yGnFKFqmIxnfeEk_7DWJpYChQBzpQfxra7d2nQNaVCM,3132
198
+ osbot_utils/helpers/html/transformers/Html_Dict__To__Html_Tags.py,sha256=VepZ9lfDYOEHupe0IowKuht-0lMD_sJFYsSVnIrcSoI,7123
199
+ osbot_utils/helpers/html/transformers/Html_Document__To__Html_Dict.py,sha256=5AE-BMpTgPzdL7f2lDgswtQS9RKDVC1w2C08jwpp54s,2509
200
+ osbot_utils/helpers/html/transformers/Html__To__Html_Dict.py,sha256=GJ4NZZ5lMFr2u0hfTpqPOMXmKLyinjCeqypg3JjME8c,4405
201
+ osbot_utils/helpers/html/transformers/Html__To__Html_Document.py,sha256=VrPGCRZhcTdNIAvjT993AfWC-6ckMElOe0nqNBoQIrU,938
202
+ osbot_utils/helpers/html/transformers/Html__To__Html_Tag.py,sha256=0uNFB0k1YQq47ZvO5aHicx_3pol8aXK5f2cBtcKKy-A,592
203
+ osbot_utils/helpers/html/transformers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
204
+ osbot_utils/helpers/html/utils/Html__Query.py,sha256=xT5_swM7UxoS76vwUykjQVWT9uaLGqEgXoOs5JyUOUo,9410
205
+ osbot_utils/helpers/html/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
202
206
  osbot_utils/helpers/llms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
203
207
  osbot_utils/helpers/llms/actions/LLM_Request__Execute.py,sha256=mgibU74brzKsO4lZEuQrs2AADDRik6WjZEb3KxiGUfE,2454
204
208
  osbot_utils/helpers/llms/actions/Type_Safe__Schema_For__LLMs.py,sha256=SfatdVI7sbFXSiEY--6FkW9amLrYUFhZw1xvgKrE_-s,12064
@@ -341,6 +345,8 @@ osbot_utils/testing/performance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
341
345
  osbot_utils/testing/performance/models/Model__Performance_Measure__Measurement.py,sha256=xT_uKzbSYo9AGiJgNmCHSt3ApneNNyKh8vsMVN6IJQ0,1127
342
346
  osbot_utils/testing/performance/models/Model__Performance_Measure__Result.py,sha256=k9HJYNLmW6sjRVsfpduSxHFiVANc1zmYtO_Oz9azpW8,755
343
347
  osbot_utils/testing/performance/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
348
+ osbot_utils/testing/test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
349
+ osbot_utils/testing/test_data/const__test__data__html.py,sha256=_DmA7OoCwvl1xxxn2aS8mfvf3Ct4bOt1KTUyTDqtwaQ,1718
344
350
  osbot_utils/type_safe/Type_Safe.py,sha256=G0HCBk52ehaJGhLYnt4cKUBsqfnxyRDxrY7_7YhktZg,6390
345
351
  osbot_utils/type_safe/Type_Safe__Base.py,sha256=IQ7ZRXG8k0mFz4bSfYZwnxdPifXaiTm2X3pHLvGc17A,8849
346
352
  osbot_utils/type_safe/Type_Safe__Primitive.py,sha256=-GBUcuFBBBKrVRSf7cmjPRbAxo7vnL4tOvr9ktmbVj4,3829
@@ -423,7 +429,7 @@ osbot_utils/type_safe/type_safe_core/shared/Type_Safe__Raise_Exception.py,sha256
423
429
  osbot_utils/type_safe/type_safe_core/shared/Type_Safe__Shared__Variables.py,sha256=SuZGl9LryQX6IpOE0I_lbzClT-h17UNylC__-M8ltTY,129
424
430
  osbot_utils/type_safe/type_safe_core/shared/Type_Safe__Validation.py,sha256=aKtlqYU5uaobgpoOnzU4kKqR7mzVLeG8YcUUbWp7n-g,19648
425
431
  osbot_utils/type_safe/type_safe_core/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
426
- osbot_utils/type_safe/type_safe_core/steps/Type_Safe__Step__Class_Kwargs.py,sha256=zyPnzvN9DWTpiqn7ljr12TaZWp0YjhDCDFWSNXBtLko,7099
432
+ osbot_utils/type_safe/type_safe_core/steps/Type_Safe__Step__Class_Kwargs.py,sha256=BbMPfCv5-RUZzh-TbyLBvykXZkdkR91jCGJoZ4R697g,8237
427
433
  osbot_utils/type_safe/type_safe_core/steps/Type_Safe__Step__Default_Kwargs.py,sha256=tzKXDUc0HVP5QvCWsmcPuuZodNvQZ9FeMDNI2x00Ngw,1943
428
434
  osbot_utils/type_safe/type_safe_core/steps/Type_Safe__Step__Default_Value.py,sha256=mRu0yV3w7Ch1H8SOfXMRqMBp3ooY95yR_oni7JafJBc,4603
429
435
  osbot_utils/type_safe/type_safe_core/steps/Type_Safe__Step__From_Json.py,sha256=GTZnGC7DvEBA_LxgLw_KZZ1iVUV0EwyIgcZzoh14Bro,15453
@@ -462,8 +468,8 @@ osbot_utils/utils/Toml.py,sha256=Rxl8gx7mni5CvBAK-Ai02EKw-GwtJdd3yeHT2kMloik,166
462
468
  osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
463
469
  osbot_utils/utils/Zip.py,sha256=mG42lgTY0tnm14T3P1-DSAIZKkTiYoO3odZ1aOUdc1I,14394
464
470
  osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
465
- osbot_utils/version,sha256=2dprv-TzJozAbapaMttCQT1_wv77Mq1Y8gfR1PL_D-k,8
466
- osbot_utils-2.75.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
467
- osbot_utils-2.75.0.dist-info/METADATA,sha256=2R9-5Mc5oJK7MyrexskI17QkHoyrfefEWycnJUJozqs,7905
468
- osbot_utils-2.75.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
469
- osbot_utils-2.75.0.dist-info/RECORD,,
471
+ osbot_utils/version,sha256=Ee_VvYF0FneCzkUtpqDTXDcXCaviuUXqsJ-W8pEco9k,8
472
+ osbot_utils-2.77.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
473
+ osbot_utils-2.77.0.dist-info/METADATA,sha256=WX8X7ud_stauh0dxr7wvg7IPLgbn5-0X1Nm993_tUQc,7918
474
+ osbot_utils-2.77.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
475
+ osbot_utils-2.77.0.dist-info/RECORD,,
@@ -1,5 +0,0 @@
1
- from osbot_utils.helpers.html.Tag__Base import Tag__Base
2
-
3
-
4
- class Tag__Body(Tag__Base):
5
- tag_name = 'body'
@@ -1,5 +0,0 @@
1
- from osbot_utils.helpers.html.Tag__Base import Tag__Base
2
-
3
-
4
- class Tag__Div(Tag__Base):
5
- tag_name = 'div'
@@ -1,5 +0,0 @@
1
- from osbot_utils.helpers.html.Tag__Base import Tag__Base
2
-
3
-
4
- class Tag__HR(Tag__Base):
5
- tag_name = 'hr'