osbot-utils 1.89.0__tar.gz → 1.91.0__tar.gz

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 (348) hide show
  1. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/PKG-INFO +2 -2
  2. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/README.md +1 -1
  3. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Type_Safe.py +20 -7
  4. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/Mermaid.py +7 -7
  5. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Zip_Bytes.py +2 -2
  6. osbot_utils-1.91.0/osbot_utils/helpers/python_compatibility/python_3_8.py +8 -0
  7. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Handler.py +21 -21
  8. osbot_utils-1.91.0/osbot_utils/helpers/type_safe/Type_Safe__Validator.py +14 -0
  9. osbot_utils-1.91.0/osbot_utils/helpers/type_safe/validators/Validator__Max.py +28 -0
  10. osbot_utils-1.91.0/osbot_utils/helpers/type_safe/validators/Validator__Min.py +38 -0
  11. osbot_utils-1.91.0/osbot_utils/helpers/type_safe/validators/Validator__One_Of.py +18 -0
  12. osbot_utils-1.91.0/osbot_utils/helpers/type_safe/validators/Validator__Regex.py +26 -0
  13. osbot_utils-1.91.0/osbot_utils/helpers/type_safe/validators/__init__.py +0 -0
  14. osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__Attribute.py +7 -0
  15. osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__Element.py +15 -0
  16. osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__File.py +9 -0
  17. osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__File__Load.py +88 -0
  18. osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__File__To_Dict.py +41 -0
  19. osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__File__To_Xml.py +72 -0
  20. osbot_utils-1.91.0/osbot_utils/helpers/xml/__init__.py +0 -0
  21. osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Channel.py +17 -0
  22. osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Enclosure.py +7 -0
  23. osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Feed.py +11 -0
  24. osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Feed__Parser.py +93 -0
  25. osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Image.py +8 -0
  26. osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Item.py +17 -0
  27. osbot_utils-1.91.0/osbot_utils/testing/__init__.py +0 -0
  28. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Objects.py +46 -10
  29. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Regex.py +1 -1
  30. osbot_utils-1.91.0/osbot_utils/utils/__init__.py +0 -0
  31. osbot_utils-1.91.0/osbot_utils/version +1 -0
  32. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/pyproject.toml +1 -1
  33. osbot_utils-1.89.0/osbot_utils/helpers/Xml_To_Dict.py +0 -87
  34. osbot_utils-1.89.0/osbot_utils/version +0 -1
  35. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/LICENSE +0 -0
  36. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/__init__.py +0 -0
  37. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Cache_Pickle.py +0 -0
  38. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Kwargs_To_Disk.py +0 -0
  39. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Kwargs_To_Self.py +0 -0
  40. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Type_Safe__Base.py +0 -0
  41. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Type_Safe__Dict.py +0 -0
  42. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Type_Safe__List.py +0 -0
  43. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/__init__.py +0 -0
  44. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/context_managers/__init__.py +0 -0
  45. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/context_managers/async_invoke.py +0 -0
  46. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/context_managers/capture_duration.py +0 -0
  47. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/context_managers/disable_root_loggers.py +0 -0
  48. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/context_managers/print_duration.py +0 -0
  49. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/__init__.py +0 -0
  50. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/classes/__init__.py +0 -0
  51. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/classes/singleton.py +0 -0
  52. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/lists/__init__.py +0 -0
  53. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/lists/filter_list.py +0 -0
  54. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/lists/group_by.py +0 -0
  55. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/lists/index_by.py +0 -0
  56. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/__init__.py +0 -0
  57. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/cache.py +0 -0
  58. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/cache_on_function.py +0 -0
  59. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/cache_on_self.py +0 -0
  60. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/cache_on_tmp.py +0 -0
  61. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/capture_exception.py +0 -0
  62. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/capture_status.py +0 -0
  63. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/catch.py +0 -0
  64. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/context.py +0 -0
  65. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/depreciated.py +0 -0
  66. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/function_type_check.py +0 -0
  67. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/obj_as_context.py +0 -0
  68. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/remove_return_value.py +0 -0
  69. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/required_fields.py +0 -0
  70. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/type_safe.py +0 -0
  71. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/fluent/Fluent_Dict.py +0 -0
  72. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/fluent/Fluent_List.py +0 -0
  73. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/fluent/__init__.py +0 -0
  74. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/__init__.py +0 -0
  75. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/Mermaid__Edge.py +0 -0
  76. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/Mermaid__Graph.py +0 -0
  77. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/Mermaid__Node.py +0 -0
  78. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/Mermaid__Renderer.py +0 -0
  79. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/configs/Mermaid__Edge__Config.py +0 -0
  80. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/configs/Mermaid__Node__Config.py +0 -0
  81. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/configs/Mermaid__Render__Config.py +0 -0
  82. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/examples/Mermaid_Examples__FlowChart.py +0 -0
  83. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/models/Mermaid__Diagram_Direction.py +0 -0
  84. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/models/Mermaid__Diagram__Type.py +0 -0
  85. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/models/Mermaid__Node__Shape.py +0 -0
  86. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph.py +0 -0
  87. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Config.py +0 -0
  88. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Data.py +0 -0
  89. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Edge.py +0 -0
  90. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Node.py +0 -0
  91. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Random_Graphs.py +0 -0
  92. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Serializer.py +0 -0
  93. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraphs.py +0 -0
  94. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/__init__.py +0 -0
  95. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/CFormat.py +0 -0
  96. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/CPrint.py +0 -0
  97. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Dependency_Manager.py +0 -0
  98. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Dict_To_Attr.py +0 -0
  99. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Guid.py +0 -0
  100. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Hashicorp_Secrets.py +0 -0
  101. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Local_Cache.py +0 -0
  102. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Local_Caches.py +0 -0
  103. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Print_Table.py +0 -0
  104. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Python_Audit.py +0 -0
  105. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Random_Guid.py +0 -0
  106. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Random_Guid_Short.py +0 -0
  107. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Random_Seed.py +0 -0
  108. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Safe_Id.py +0 -0
  109. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Str_ASCII.py +0 -0
  110. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Timestamp_Now.py +0 -0
  111. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Type_Registry.py +0 -0
  112. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Type_Safe_Method.py +0 -0
  113. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/__init__.py +0 -0
  114. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast.py +0 -0
  115. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Base.py +0 -0
  116. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Data.py +0 -0
  117. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Load.py +0 -0
  118. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Merge.py +0 -0
  119. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Node.py +0 -0
  120. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Visit.py +0 -0
  121. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Call_Tree.py +0 -0
  122. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/__init__.py +0 -0
  123. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Add.py +0 -0
  124. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Alias.py +0 -0
  125. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_And.py +0 -0
  126. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Argument.py +0 -0
  127. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Arguments.py +0 -0
  128. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Assert.py +0 -0
  129. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Assign.py +0 -0
  130. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Attribute.py +0 -0
  131. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Aug_Assign.py +0 -0
  132. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Bin_Op.py +0 -0
  133. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Bool_Op.py +0 -0
  134. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Break.py +0 -0
  135. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Call.py +0 -0
  136. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Class_Def.py +0 -0
  137. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Compare.py +0 -0
  138. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Comprehension.py +0 -0
  139. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Constant.py +0 -0
  140. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Continue.py +0 -0
  141. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Dict.py +0 -0
  142. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Eq.py +0 -0
  143. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Except_Handler.py +0 -0
  144. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Expr.py +0 -0
  145. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_For.py +0 -0
  146. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Function_Def.py +0 -0
  147. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Generator_Exp.py +0 -0
  148. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Gt.py +0 -0
  149. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_GtE.py +0 -0
  150. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_If.py +0 -0
  151. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_If_Exp.py +0 -0
  152. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Import.py +0 -0
  153. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Import_From.py +0 -0
  154. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_In.py +0 -0
  155. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Is.py +0 -0
  156. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Is_Not.py +0 -0
  157. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Keyword.py +0 -0
  158. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Lambda.py +0 -0
  159. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_List.py +0 -0
  160. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_List_Comp.py +0 -0
  161. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Load.py +0 -0
  162. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Lt.py +0 -0
  163. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_LtE.py +0 -0
  164. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Mod.py +0 -0
  165. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Module.py +0 -0
  166. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Mult.py +0 -0
  167. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Name.py +0 -0
  168. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Not.py +0 -0
  169. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Not_Eq.py +0 -0
  170. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Not_In.py +0 -0
  171. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Or.py +0 -0
  172. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Pass.py +0 -0
  173. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Pow.py +0 -0
  174. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Raise.py +0 -0
  175. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Return.py +0 -0
  176. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Set.py +0 -0
  177. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Slice.py +0 -0
  178. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Starred.py +0 -0
  179. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Store.py +0 -0
  180. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Sub.py +0 -0
  181. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Subscript.py +0 -0
  182. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Try.py +0 -0
  183. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Tuple.py +0 -0
  184. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Unary_Op.py +0 -0
  185. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_While.py +0 -0
  186. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_With.py +0 -0
  187. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_With_Item.py +0 -0
  188. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Yield.py +0 -0
  189. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/__init__.py +0 -0
  190. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Actions.py +0 -0
  191. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Config.py +0 -0
  192. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Data.py +0 -0
  193. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Invoke.py +0 -0
  194. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Row.py +0 -0
  195. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Table.py +0 -0
  196. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/__init__.py +0 -0
  197. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/flows/flow__Cache__Requests.py +0 -0
  198. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/Flow.py +0 -0
  199. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/Flow__Events.py +0 -0
  200. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/Task.py +0 -0
  201. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/__init__.py +0 -0
  202. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/decorators/__init__.py +0 -0
  203. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/decorators/flow.py +0 -0
  204. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/decorators/task.py +0 -0
  205. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/models/Flow_Run__Config.py +0 -0
  206. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/models/Flow_Run__Event.py +0 -0
  207. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/models/Flow_Run__Event_Data.py +0 -0
  208. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/models/Flow_Run__Event_Type.py +0 -0
  209. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/models/__init__.py +0 -0
  210. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/generators/Generator_Context_Manager.py +0 -0
  211. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/generators/Generator_Manager.py +0 -0
  212. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/generators/Model__Generator_State.py +0 -0
  213. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/generators/Model__Generator_Target.py +0 -0
  214. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/generators/__init__.py +0 -0
  215. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Dict_To_Css.py +0 -0
  216. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Dict_To_Html.py +0 -0
  217. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Dict_To_Tags.py +0 -0
  218. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Html_To_Dict.py +0 -0
  219. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Html_To_Tag.py +0 -0
  220. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Base.py +0 -0
  221. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Body.py +0 -0
  222. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Div.py +0 -0
  223. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__H.py +0 -0
  224. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__HR.py +0 -0
  225. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Head.py +0 -0
  226. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Html.py +0 -0
  227. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Link.py +0 -0
  228. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Style.py +0 -0
  229. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/__init__.py +0 -0
  230. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/Event__Queue.py +0 -0
  231. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/PubSub__Client.py +0 -0
  232. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/PubSub__Room.py +0 -0
  233. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/PubSub__Server.py +0 -0
  234. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/PubSub__Sqlite.py +0 -0
  235. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/__init__.py +0 -0
  236. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event.py +0 -0
  237. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Connect.py +0 -0
  238. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Disconnect.py +0 -0
  239. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Execute_Method.py +0 -0
  240. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Join_Room.py +0 -0
  241. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Leave_Room.py +0 -0
  242. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Message.py +0 -0
  243. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__PubSub__Client.py +0 -0
  244. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/__init__.py +0 -0
  245. {osbot_utils-1.89.0/osbot_utils/helpers/sqlite → osbot_utils-1.91.0/osbot_utils/helpers/python_compatibility}/__init__.py +0 -0
  246. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Capture_Sqlite_Error.py +0 -0
  247. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Cursor.py +0 -0
  248. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Database.py +0 -0
  249. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Field.py +0 -0
  250. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Globals.py +0 -0
  251. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Table.py +0 -0
  252. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Table__Create.py +0 -0
  253. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Temp_Sqlite__Database__Disk.py +0 -0
  254. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Temp_Sqlite__Table.py +0 -0
  255. {osbot_utils-1.89.0/osbot_utils/helpers/sqlite/cache → osbot_utils-1.91.0/osbot_utils/helpers/sqlite}/__init__.py +0 -0
  256. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Schema__Table__Requests.py +0 -0
  257. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests.py +0 -0
  258. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Patch.py +0 -0
  259. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Sqlite.py +0 -0
  260. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Table.py +0 -0
  261. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Sqlite__DB__Requests.py +0 -0
  262. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/TestCase__Sqlite__Cache__Requests.py +0 -0
  263. {osbot_utils-1.89.0/osbot_utils/helpers/sqlite/domains → osbot_utils-1.91.0/osbot_utils/helpers/sqlite/cache}/__init__.py +0 -0
  264. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB.py +0 -0
  265. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Files.py +0 -0
  266. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Graph.py +0 -0
  267. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Json.py +0 -0
  268. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Local.py +0 -0
  269. {osbot_utils-1.89.0/osbot_utils/helpers/sqlite/domains/schemas → osbot_utils-1.91.0/osbot_utils/helpers/sqlite/domains}/__init__.py +0 -0
  270. {osbot_utils-1.89.0/osbot_utils/helpers/sqlite/models → osbot_utils-1.91.0/osbot_utils/helpers/sqlite/domains/schemas}/__init__.py +0 -0
  271. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/models/Sqlite__Field__Type.py +0 -0
  272. {osbot_utils-1.89.0/osbot_utils/helpers/sqlite/sample_data → osbot_utils-1.91.0/osbot_utils/helpers/sqlite/models}/__init__.py +0 -0
  273. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/sample_data/Sqlite__Sample_Data__Chinook.py +0 -0
  274. {osbot_utils-1.89.0/osbot_utils/helpers/sqlite/sql_builder → osbot_utils-1.91.0/osbot_utils/helpers/sqlite/sample_data}/__init__.py +0 -0
  275. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/sql_builder/SQL_Builder.py +0 -0
  276. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/sql_builder/SQL_Builder__Select.py +0 -0
  277. {osbot_utils-1.89.0/osbot_utils/helpers/sqlite/tables → osbot_utils-1.91.0/osbot_utils/helpers/sqlite/sql_builder}/__init__.py +0 -0
  278. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Config.py +0 -0
  279. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Edges.py +0 -0
  280. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Files.py +0 -0
  281. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Nodes.py +0 -0
  282. {osbot_utils-1.89.0/osbot_utils/helpers/ssh → osbot_utils-1.91.0/osbot_utils/helpers/sqlite/tables}/__init__.py +0 -0
  283. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SCP.py +0 -0
  284. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH.py +0 -0
  285. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Cache__Requests.py +0 -0
  286. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Execute.py +0 -0
  287. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Health_Check.py +0 -0
  288. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Linux.py +0 -0
  289. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Linux__Amazon.py +0 -0
  290. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Python.py +0 -0
  291. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/TestCase__SSH.py +0 -0
  292. {osbot_utils-1.89.0/osbot_utils/helpers/trace → osbot_utils-1.91.0/osbot_utils/helpers/ssh}/__init__.py +0 -0
  293. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call.py +0 -0
  294. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Config.py +0 -0
  295. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Graph.py +0 -0
  296. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Print_Lines.py +0 -0
  297. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Print_Traces.py +0 -0
  298. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Stack.py +0 -0
  299. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Stack_Node.py +0 -0
  300. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Stats.py +0 -0
  301. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__View_Model.py +0 -0
  302. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Files.py +0 -0
  303. {osbot_utils-1.89.0/osbot_utils/testing → osbot_utils-1.91.0/osbot_utils/helpers/trace}/__init__.py +0 -0
  304. {osbot_utils-1.89.0/osbot_utils/utils → osbot_utils-1.91.0/osbot_utils/helpers/type_safe}/__init__.py +0 -0
  305. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Catch.py +0 -0
  306. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Custom_Handler_For_Http_Tests.py +0 -0
  307. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Duration.py +0 -0
  308. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Hook_Method.py +0 -0
  309. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Log_To_Queue.py +0 -0
  310. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Log_To_String.py +0 -0
  311. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Logging.py +0 -0
  312. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Patch_Print.py +0 -0
  313. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Profiler.py +0 -0
  314. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Pytest.py +0 -0
  315. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Stderr.py +0 -0
  316. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Stdout.py +0 -0
  317. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Env_Vars.py +0 -0
  318. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_File.py +0 -0
  319. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Folder.py +0 -0
  320. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Sys_Path.py +0 -0
  321. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Web_Server.py +0 -0
  322. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Zip.py +0 -0
  323. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Zip_In_Memory.py +0 -0
  324. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Unit_Test.py +0 -0
  325. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Unzip_File.py +0 -0
  326. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Assert.py +0 -0
  327. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Call_Stack.py +0 -0
  328. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Csv.py +0 -0
  329. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Dev.py +0 -0
  330. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Env.py +0 -0
  331. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Exceptions.py +0 -0
  332. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Files.py +0 -0
  333. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Functions.py +0 -0
  334. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Http.py +0 -0
  335. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Int.py +0 -0
  336. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Json.py +0 -0
  337. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Json_Cache.py +0 -0
  338. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Lists.py +0 -0
  339. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Misc.py +0 -0
  340. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Png.py +0 -0
  341. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Process.py +0 -0
  342. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Python_Logger.py +0 -0
  343. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Status.py +0 -0
  344. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Str.py +0 -0
  345. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Threads.py +0 -0
  346. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Toml.py +0 -0
  347. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Version.py +0 -0
  348. {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Zip.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: osbot_utils
3
- Version: 1.89.0
3
+ Version: 1.91.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.89.0-blue)
26
+ ![Current Release](https://img.shields.io/badge/release-v1.91.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 @@
2
2
 
3
3
  Powerful Python util methods and classes that simplify common apis and tasks.
4
4
 
5
- ![Current Release](https://img.shields.io/badge/release-v1.89.0-blue)
5
+ ![Current Release](https://img.shields.io/badge/release-v1.91.0-blue)
6
6
  [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](https://codecov.io/gh/owasp-sbot/OSBot-Utils)
7
7
 
8
8
 
@@ -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
@@ -24,6 +24,7 @@ if sys.version_info < (3, 8): # pragma
24
24
  return ()
25
25
  else:
26
26
  from typing import get_origin, get_args, ForwardRef
27
+ from osbot_utils.helpers.python_compatibility.python_3_8 import Annotated
27
28
 
28
29
  if sys.version_info >= (3, 10):
29
30
  NoneType = types.NoneType
@@ -44,7 +45,6 @@ class Type_Safe:
44
45
 
45
46
  for (key, value) in self.__cls_kwargs__().items(): # assign all default values to self
46
47
  if value is not None: # when the value is explicitly set to None on the class static vars, we can't check for type safety
47
-
48
48
  raise_exception_on_obj_type_annotation_mismatch(self, key, value)
49
49
  if hasattr(self, key):
50
50
  existing_value = getattr(self, key)
@@ -65,10 +65,11 @@ class Type_Safe:
65
65
  def __exit__(self, exc_type, exc_val, exc_tb): pass
66
66
 
67
67
  def __setattr__(self, name, value):
68
- from osbot_utils.utils.Objects import convert_dict_to_value_from_obj_annotation
69
- from osbot_utils.utils.Objects import convert_to_value_from_obj_annotation
70
- from osbot_utils.utils.Objects import value_type_matches_obj_annotation_for_attr
71
- from osbot_utils.utils.Objects import value_type_matches_obj_annotation_for_union_attr
68
+ from osbot_utils.utils.Objects import convert_dict_to_value_from_obj_annotation
69
+ from osbot_utils.utils.Objects import convert_to_value_from_obj_annotation
70
+ from osbot_utils.utils.Objects import value_type_matches_obj_annotation_for_attr
71
+ from osbot_utils.utils.Objects import value_type_matches_obj_annotation_for_union_and_annotated
72
+ from osbot_utils.helpers.type_safe.Type_Safe__Validator import Type_Safe__Validator
72
73
 
73
74
  if not hasattr(self, '__annotations__'): # can't do type safety checks if the class does not have annotations
74
75
  return super().__setattr__(name, value)
@@ -79,7 +80,7 @@ class Type_Safe:
79
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)
80
81
  value = convert_to_value_from_obj_annotation (self, name, value)
81
82
  check_1 = value_type_matches_obj_annotation_for_attr (self, name, value)
82
- check_2 = value_type_matches_obj_annotation_for_union_attr(self, name, value)
83
+ check_2 = value_type_matches_obj_annotation_for_union_and_annotated(self, name, value)
83
84
  if (check_1 is False and check_2 is None or
84
85
  check_1 is None and check_2 is False or
85
86
  check_1 is False and check_2 is False ): # fix for type safety assigment on Union vars
@@ -89,6 +90,16 @@ class Type_Safe:
89
90
  if getattr(self, name) is not None: # unless it is already set to None
90
91
  raise ValueError(f"Can't set None, to a variable that is already set. Invalid type for attribute '{name}'. Expected '{self.__annotations__.get(name)}' but got '{type(value)}'")
91
92
 
93
+ # todo: refactor this to separate method
94
+ if hasattr(self.__annotations__, 'get'):
95
+ annotation = self.__annotations__.get(name)
96
+ if annotation and get_origin(annotation) is Annotated:
97
+ annotation_args = get_args(annotation)
98
+ target_type = annotation_args[0]
99
+ for attribute in annotation_args[1:]:
100
+ if isinstance(attribute, Type_Safe__Validator):
101
+ attribute.validate(value=value, field_name=name, target_type=target_type)
102
+
92
103
  super().__setattr__(name, value)
93
104
 
94
105
  def __attr_names__(self):
@@ -131,6 +142,8 @@ class Type_Safe:
131
142
  else:
132
143
  var_value = getattr(base_cls, var_name)
133
144
  if var_value is not None: # allow None assignments on ctor since that is a valid use case
145
+ if get_origin(var_type) is Annotated:
146
+ continue
134
147
  if var_type and not isinstance(var_value, var_type): # check type
135
148
  exception_message = f"variable '{var_name}' is defined as type '{var_type}' but has value '{var_value}' of type '{type(var_value)}'"
136
149
  raise ValueError(exception_message)
@@ -1,10 +1,10 @@
1
- from osbot_utils.graphs.mermaid.Mermaid__Renderer import Mermaid__Renderer
2
- from osbot_utils.graphs.mermaid.Mermaid__Edge import Mermaid__Edge
3
- from osbot_utils.graphs.mermaid.Mermaid__Graph import Mermaid__Graph
4
- from osbot_utils.graphs.mermaid.models.Mermaid__Diagram_Direction import Diagram__Direction
5
- from osbot_utils.graphs.mermaid.models.Mermaid__Diagram__Type import Diagram__Type
6
- from osbot_utils.utils.Python_Logger import Python_Logger
7
- from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
1
+ from osbot_utils.graphs.mermaid.Mermaid__Renderer import Mermaid__Renderer
2
+ from osbot_utils.graphs.mermaid.Mermaid__Edge import Mermaid__Edge
3
+ from osbot_utils.graphs.mermaid.Mermaid__Graph import Mermaid__Graph
4
+ from osbot_utils.graphs.mermaid.models.Mermaid__Diagram_Direction import Diagram__Direction
5
+ from osbot_utils.graphs.mermaid.models.Mermaid__Diagram__Type import Diagram__Type
6
+ from osbot_utils.utils.Python_Logger import Python_Logger
7
+ from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
8
8
 
9
9
  class Mermaid(Kwargs_To_Self):
10
10
  graph : Mermaid__Graph
@@ -2,10 +2,10 @@ from osbot_utils.base_classes.Type_Safe import Type_Safe
2
2
  from osbot_utils.utils.Dev import pprint
3
3
  from osbot_utils.utils.Files import files_list, file_create_from_bytes, temp_file, parent_folder, parent_folder_create
4
4
  from osbot_utils.utils.Misc import random_text
5
- from osbot_utils.utils.Regex import list__match_regex, list__match_regexes
5
+ from osbot_utils.utils.Regex import list__match_regexes
6
6
  from osbot_utils.utils.Zip import zip_bytes_empty, zip_bytes__files, zip_bytes__add_file, zip_bytes__add_files, \
7
7
  zip_bytes__replace_files, zip_bytes__replace_file, zip_bytes__file_list, zip_bytes__file, \
8
- zip_bytes__add_file__from_disk, zip_bytes__add_files__from_disk, zip_files, zip_file__files, zip_bytes__remove_files
8
+ zip_bytes__add_file__from_disk, zip_bytes__add_files__from_disk, zip_file__files, zip_bytes__remove_files
9
9
 
10
10
 
11
11
  class Zip_Bytes(Type_Safe):
@@ -0,0 +1,8 @@
1
+ import sys
2
+
3
+ if sys.version_info < (3, 9):
4
+ class Annotated:
5
+ def __init__(self, *args) -> None:
6
+ pass
7
+ else:
8
+ from typing import Annotated
@@ -8,28 +8,28 @@ from osbot_utils.helpers.trace.Trace_Call__Stack_Node import Trace_Call__Stack
8
8
  from osbot_utils.helpers.trace.Trace_Call__Stats import Trace_Call__Stats
9
9
 
10
10
  DEFAULT_ROOT_NODE_NODE_TITLE = 'Trace Session'
11
- GLOBAL_FUNCTIONS_TO_IGNORE = ['value_type_matches_obj_annotation_for_attr' , # these are type safety functions which introduce quite a lot of noise in the traces (and unless one is debugging type safety, they will not be needed)
12
- 'value_type_matches_obj_annotation_for_union_attr' , # todo: map out and document why exactly these methods are ignore (and what is the side effect)
13
- 'are_types_compatible_for_assigment' ,
14
- 'obj_attribute_annotation' ,
15
- 'get_origin' ,
16
- 'getmro' ,
17
- 'default_value' ,
18
- 'raise_exception_on_obj_type_annotation_mismatch' ,
19
- '__cls_kwargs__' ,
20
- '__default__value__' ,
21
- '__setattr__' ,
11
+ GLOBAL_FUNCTIONS_TO_IGNORE = ['value_type_matches_obj_annotation_for_attr' , # these are type safety functions which introduce quite a lot of noise in the traces (and unless one is debugging type safety, they will not be needed)
12
+ 'value_type_matches_obj_annotation_for_union_and_annotated' , # todo: map out and document why exactly these methods are ignore (and what is the side effect)
13
+ 'are_types_compatible_for_assigment' ,
14
+ 'obj_attribute_annotation' ,
15
+ 'get_origin' ,
16
+ 'getmro' ,
17
+ 'default_value' ,
18
+ 'raise_exception_on_obj_type_annotation_mismatch' ,
19
+ '__cls_kwargs__' ,
20
+ '__default__value__' ,
21
+ '__setattr__' ,
22
22
  '<module>']
23
- GLOBAL_MODULES_TO_IGNORE = ['osbot_utils.helpers.trace.Trace_Call' , # todo: map out and document why exactly these modules are ignore (and what is the side effect)
24
- 'osbot_utils.helpers.trace.Trace_Call__Config' ,
25
- 'osbot_utils.helpers.trace.Trace_Call__View_Model' ,
26
- 'osbot_utils.helpers.trace.Trace_Call__Print_Traces' ,
27
- 'osbot_utils.helpers.trace.Trace_Call__Stack' ,
28
- 'osbot_utils.base_classes.Type_Safe' ,
29
- 'osbot_utils.helpers.CPrint' , # also see if this should be done here or at the print/view stage
30
- 'osbot_utils.helpers.Print_Table' ,
31
- 'osbot_utils.decorators.methods.cache_on_self' ,
32
- 'codecs' ]
23
+ GLOBAL_MODULES_TO_IGNORE = ['osbot_utils.helpers.trace.Trace_Call' , # todo: map out and document why exactly these modules are ignore (and what is the side effect)
24
+ 'osbot_utils.helpers.trace.Trace_Call__Config' ,
25
+ 'osbot_utils.helpers.trace.Trace_Call__View_Model' ,
26
+ 'osbot_utils.helpers.trace.Trace_Call__Print_Traces' ,
27
+ 'osbot_utils.helpers.trace.Trace_Call__Stack' ,
28
+ 'osbot_utils.base_classes.Type_Safe' ,
29
+ 'osbot_utils.helpers.CPrint' , # also see if this should be done here or at the print/view stage
30
+ 'osbot_utils.helpers.Print_Table' ,
31
+ 'osbot_utils.decorators.methods.cache_on_self' ,
32
+ 'codecs' ]
33
33
 
34
34
  #GLOBAL_MODULES_TO_IGNORE = []
35
35
  #GLOBAL_FUNCTIONS_TO_IGNORE = []
@@ -0,0 +1,14 @@
1
+ from osbot_utils.helpers.python_compatibility.python_3_8 import Annotated
2
+ from typing import Any
3
+
4
+ class Type_Safe__Validator: # Base class for all Type_Safe validators.
5
+
6
+ def validate(self, value: Any, field_name: str, target_type: type) -> None: # Validate a value against this validator's rules.
7
+ if value and type(value) != target_type:
8
+ raise ValueError(f"{field_name} must be of type {target_type}, got {type(value)}")
9
+
10
+ def describe(self) -> str: # Return a human-readable description of this validator's rules.
11
+ pass
12
+
13
+
14
+ Validate = Annotated
@@ -0,0 +1,28 @@
1
+ from typing import Any
2
+ from osbot_utils.helpers.type_safe.Type_Safe__Validator import Type_Safe__Validator
3
+
4
+
5
+ class Validator__Max(Type_Safe__Validator): # Validates that a numeric value is at most the specified maximum."""
6
+ max_value: float
7
+
8
+ def __init__(self, max_value):
9
+ self.max_value = max_value
10
+
11
+ def validate(self, value: Any, field_name: str, target_type: type) -> None:
12
+ super().validate(value=value, field_name=field_name, target_type=target_type)
13
+ if value is None:
14
+ return
15
+ compare_value = value if isinstance(value, (int, float)) else len(value)
16
+ if compare_value > self.max_value:
17
+ if not isinstance(value, (int, float)):
18
+ msg = f"{field_name} must be at most {self.max_value}, got {compare_value}"
19
+ elif isinstance(value, (list, tuple)):
20
+ msg = f"{field_name} must be at most {self.max_value}, got length {compare_value}"
21
+ else:
22
+ msg = f"{field_name} must be at most {self.max_value}, got size {compare_value}"
23
+ raise ValueError(msg)
24
+
25
+ def describe(self) -> str:
26
+ return f"maximum value: {self.max_value}"
27
+
28
+ Max = Validator__Max
@@ -0,0 +1,38 @@
1
+ from typing import Any
2
+ from osbot_utils.helpers.type_safe.Type_Safe__Validator import Type_Safe__Validator
3
+
4
+ class Validator__Min(Type_Safe__Validator): # Validates that a value is at least the specified minimum. Works with any type that supports the < operator (numbers, strings, lists, etc.)
5
+ min_value: Any
6
+
7
+ def __init__(self, min_value):
8
+ super().__init__()
9
+ self.min_value = min_value
10
+
11
+ def validate(self, value: Any, field_name: str, target_type: type) -> None:
12
+ super().validate(value=value, field_name=field_name, target_type=target_type)
13
+ if value is None: # can't compare if value has been set to None
14
+ return
15
+
16
+ try:
17
+ compare_value = value if isinstance(value, (int, float)) else len(value)
18
+
19
+ if compare_value < self.min_value:
20
+ if isinstance(value, (int, float)):
21
+ msg = f"{field_name} must be at least {self.min_value}, got {compare_value}"
22
+ elif isinstance(value, str):
23
+ msg = f"{field_name} must have length at least {self.min_value}, got length {compare_value}"
24
+ elif isinstance(value, (list, tuple)):
25
+ msg = f"{field_name} must have length at least {self.min_value}, got length {compare_value}"
26
+ else:
27
+ msg = f"{field_name} must have size at least {self.min_value}, got size {compare_value}"
28
+ raise ValueError(msg)
29
+ except TypeError:
30
+ raise ValueError(f"Cannot compare {field_name} of type {type(value)} with minimum value of type {type(self.min_value)}")
31
+
32
+ def describe(self) -> str:
33
+ if isinstance(self.min_value, (int, float)):
34
+ return f"minimum value: {self.min_value}"
35
+ else:
36
+ return f"minimum length: {len(self.min_value)}"
37
+
38
+ Min = Validator__Min
@@ -0,0 +1,18 @@
1
+ from typing import Any
2
+ from osbot_utils.helpers.type_safe.Type_Safe__Validator import Type_Safe__Validator
3
+
4
+
5
+ class Validator__One_Of(Type_Safe__Validator): # Validates that a value is one of a set of allowed values."""
6
+ allowed: list
7
+
8
+ def __init__(self, allowed):
9
+ self.allowed = allowed
10
+
11
+ def validate(self, value: Any, field_name: str, target_type:type) -> None:
12
+ if value not in self.allowed:
13
+ raise ValueError(f"{field_name} must be one of {self.allowed}, got {value}")
14
+
15
+ def describe(self) -> str:
16
+ return f"must be one of: {self.allowed}"
17
+
18
+ One_Of = Validator__One_Of
@@ -0,0 +1,26 @@
1
+ from typing import Any
2
+ from osbot_utils.helpers.type_safe.Type_Safe__Validator import Type_Safe__Validator
3
+
4
+ class Validator__Regex(Type_Safe__Validator): # Validates that a string matches the specified regex pattern.
5
+ pattern : str
6
+ description: str
7
+
8
+ def __init__(self, pattern, description=None):
9
+ self.pattern = pattern
10
+ self.description = description
11
+
12
+ def validate(self, value: Any, field_name: str, target_type:type) -> None:
13
+ import re
14
+ if value is None:
15
+ return
16
+ if not isinstance(value, str):
17
+ raise ValueError(f"{field_name} must be a string, got {type(value)}")
18
+ if not re.match(self.pattern, value):
19
+ raise ValueError(f"{field_name} must match pattern {self.pattern}")
20
+
21
+ def describe(self) -> str:
22
+ if self.description:
23
+ return self.description
24
+ return f"must match pattern: {self.pattern}"
25
+
26
+ Regex = Validator__Regex
@@ -0,0 +1,7 @@
1
+ from osbot_utils.base_classes.Type_Safe import Type_Safe
2
+
3
+
4
+ class Xml__Attribute(Type_Safe):
5
+ name : str
6
+ value : str
7
+ namespace: str
@@ -0,0 +1,15 @@
1
+ from typing import Dict, List, Union
2
+ from osbot_utils.base_classes.Type_Safe import Type_Safe
3
+ from osbot_utils.helpers.xml.Xml__Attribute import Xml__Attribute
4
+
5
+ class XML__Element(Type_Safe):
6
+ tag : str # Element's local name
7
+ namespace : str # Element's namespace URI
8
+ namespace_prefix: str # Element's namespace prefix
9
+ attributes : Dict[str, Xml__Attribute] # Element attributes
10
+ children : List[Union[str, 'XML__Element']] # Child elements/text
11
+
12
+ # def qualified_name(self) -> str: # Get fully qualified name with prefix
13
+ # if self.namespace_prefix:
14
+ # return f"{self.namespace_prefix}:{self.tag}"
15
+ # return self.tag
@@ -0,0 +1,9 @@
1
+ from typing import Dict
2
+ from osbot_utils.base_classes.Type_Safe import Type_Safe
3
+ from osbot_utils.helpers.xml.Xml__Element import XML__Element
4
+
5
+ class Xml__File(Type_Safe):
6
+ xml_data : str # Raw XML content
7
+ root_element: XML__Element # Parsed root element
8
+ namespaces : Dict[str, str] # XML namespace mappings
9
+
@@ -0,0 +1,88 @@
1
+ from io import StringIO
2
+ from typing import List, Union, Dict
3
+ from xml.etree.ElementTree import iterparse, Element, fromstring, ParseError
4
+ from osbot_utils.base_classes.Type_Safe import Type_Safe
5
+ from osbot_utils.helpers.xml.Xml__Attribute import Xml__Attribute
6
+ from osbot_utils.helpers.xml.Xml__Element import XML__Element
7
+ from osbot_utils.helpers.xml.Xml__File import Xml__File
8
+
9
+
10
+ class Xml__File__Load(Type_Safe):
11
+
12
+ def load_from_string(self, xml_data: str) -> Xml__File: # Create Xml__File from string
13
+ xml_file = Xml__File(xml_data=xml_data)
14
+ self.load_namespaces(xml_file)
15
+ self.parse_xml (xml_file)
16
+ return xml_file
17
+
18
+ def load_namespaces(self, xml_file: Xml__File): # Extract namespaces from XML
19
+ if not xml_file.xml_data:
20
+ raise ValueError("XML data cannot be empty")
21
+
22
+ for event, elem in iterparse(StringIO(xml_file.xml_data), events=("start-ns",)):
23
+ prefix, uri = elem
24
+ xml_file.namespaces[prefix] = uri
25
+
26
+ def parse_xml(self, xml_file: Xml__File): # Parse XML into type-safe structure
27
+ if not xml_file.xml_data:
28
+ raise ValueError("XML data cannot be empty")
29
+
30
+ try:
31
+ root = fromstring(xml_file.xml_data)
32
+ namespaces = xml_file.namespaces
33
+ xml_file.root_element = self.convert_element(namespaces,root)
34
+ except ParseError as error:
35
+ raise ValueError(f"Invalid XML: {str(error)}")
36
+
37
+ def convert_element(self, namespaces: Dict[str,str], element: Element) -> XML__Element:
38
+ attributes = self.convert_attributes(element)
39
+ children: List[Union[str, XML__Element]] = []
40
+
41
+ tag = element.tag
42
+ namespace = ''
43
+ namespace_prefix = ''
44
+
45
+ if '}' in tag:
46
+ namespace, tag = tag.split('}', 1) # Split namespace and tag
47
+ namespace = namespace[1:] # Remove the '{' prefix
48
+
49
+ for prefix, uri in namespaces.items(): # Find prefix for this namespace
50
+ if uri == namespace:
51
+ namespace_prefix = prefix
52
+ break
53
+
54
+ # Handle text content
55
+ if element.text and element.text.strip():
56
+ children.append(element.text.strip())
57
+
58
+ # Process child elements
59
+ for child in element:
60
+ child_element = self.convert_element(namespaces, child)
61
+ children.append(child_element)
62
+
63
+ if child.tail and child.tail.strip():
64
+ children.append(child.tail.strip())
65
+
66
+ return XML__Element(tag=tag,
67
+ namespace=namespace,
68
+ namespace_prefix=namespace_prefix,
69
+ attributes=attributes,
70
+ children=children)
71
+
72
+ def convert_attributes(self, element: Element) -> Dict[str, Xml__Attribute]: # Convert element attributes
73
+ attributes = {}
74
+ for key, value in element.attrib.items():
75
+ if '}' in key: # Handle namespaced attributes
76
+ namespace, name = key.split('}', 1)
77
+ namespace = namespace[1:] # Remove the '{' prefix
78
+ else:
79
+ namespace = ''
80
+ name = key
81
+
82
+ attribute = Xml__Attribute(
83
+ name=name,
84
+ value=value,
85
+ namespace=namespace
86
+ )
87
+ attributes[key] = attribute
88
+ return attributes
@@ -0,0 +1,41 @@
1
+ from typing import Dict, Any
2
+ from osbot_utils.base_classes.Type_Safe import Type_Safe
3
+ from osbot_utils.helpers.xml.Xml__Element import XML__Element
4
+ from osbot_utils.helpers.xml.Xml__File import Xml__File
5
+
6
+
7
+ class Xml__File__To_Dict(Type_Safe):
8
+ def to_dict(self, xml_file: Xml__File) -> Dict[str, Any]: # Convert Xml__File to dictionary
9
+ if not xml_file.root_element:
10
+ return {}
11
+ return self.element_to_dict(xml_file.root_element)
12
+
13
+ def element_to_dict(self, element: XML__Element) -> Dict[str, Any]: # Convert XML__Element to dictionary
14
+ result = {}
15
+
16
+ for key, attr in element.attributes.items(): # Convert attributes first
17
+ result[key] = attr.value
18
+
19
+
20
+ child_nodes: Dict[str, Any] = {} # Process children and collect text content
21
+ text_content = []
22
+ for child in element.children:
23
+ if isinstance(child, str):
24
+ text_content.append(child)
25
+ else:
26
+ if child.tag in child_nodes: # Handle child elements
27
+ if not isinstance(child_nodes[child.tag], list):
28
+ child_nodes[child.tag] = [child_nodes[child.tag]]
29
+ child_nodes[child.tag].append(self.element_to_dict(child))
30
+ else:
31
+ child_nodes[child.tag] = self.element_to_dict(child)
32
+
33
+ if text_content: # Handle text content
34
+ text_value = ' '.join(text_content)
35
+ if child_nodes or result: # If we have attributes or child nodes
36
+ result['#text'] = text_value # Add text as a special key
37
+ else:
38
+ return text_value # Return just the text if no attributes/children
39
+
40
+ result.update(child_nodes) # Merge child nodes into result
41
+ return result
@@ -0,0 +1,72 @@
1
+ from typing import Optional
2
+ from xml.etree.ElementTree import Element, SubElement, tostring
3
+ from xml.dom import minidom
4
+ from osbot_utils.base_classes.Type_Safe import Type_Safe
5
+ from osbot_utils.helpers.xml.Xml__Element import XML__Element
6
+ from osbot_utils.helpers.xml.Xml__File import Xml__File
7
+
8
+ class Xml__File__To_Xml(Type_Safe):
9
+
10
+ def convert_to_xml(self, xml_file: Xml__File, pretty_print: bool = True) -> str:
11
+ if not xml_file.root_element:
12
+ raise ValueError("XML file must have a root element")
13
+
14
+ # Create XML element tree
15
+ root = self.create_element(xml_file.root_element, xml_file.namespaces)
16
+
17
+ # Add all namespace declarations to root element
18
+ for prefix, uri in xml_file.namespaces.items():
19
+ if prefix == '':
20
+ root.set('xmlns', uri)
21
+ else:
22
+ root.set(f'xmlns:{prefix}', uri)
23
+
24
+ # Convert to string
25
+ xml_string = tostring(root, encoding='unicode', method='xml')
26
+
27
+ # Pretty print if requested
28
+ if pretty_print:
29
+ return self.pretty_print(xml_string)
30
+ return xml_string
31
+
32
+ def create_element(self, xml_element: XML__Element, namespaces: Optional[dict] = None, parent: Optional[Element] = None) -> Element:
33
+ # Create tag with namespace if applicable
34
+ tag = xml_element.tag
35
+ if xml_element.namespace_prefix:
36
+ tag = f"{xml_element.namespace_prefix}:{tag}"
37
+ # Don't add namespace URI for default namespace - let it be inherited
38
+
39
+ # Create new element or sub-element
40
+ if parent is not None:
41
+ element = SubElement(parent, tag)
42
+ else:
43
+ element = Element(tag)
44
+
45
+ # Add attributes including namespace declarations
46
+ for attr_key, attr in xml_element.attributes.items():
47
+ if attr.namespace:
48
+ attr_name = f"{{{attr.namespace}}}{attr.name}"
49
+ else:
50
+ attr_name = attr.name
51
+ element.set(attr_name, attr.value)
52
+
53
+ # Process children
54
+ text_parts = []
55
+ for child in xml_element.children:
56
+ if isinstance(child, str):
57
+ text_parts.append(child)
58
+ elif isinstance(child, XML__Element):
59
+ self.create_element(child, namespaces, element)
60
+
61
+ # Set text content if any
62
+ if text_parts:
63
+ element.text = ''.join(text_parts)
64
+
65
+ return element
66
+
67
+ def pretty_print(self, xml_string: str) -> str:
68
+ """Format XML string with proper indentation."""
69
+ parsed = minidom.parseString(xml_string)
70
+ pretty_xml = parsed.toprettyxml(indent=' ').rstrip() + '\n'
71
+ # Remove empty lines (common issue with toprettyxml)
72
+ return '\n'.join(line for line in pretty_xml.split('\n') if line.strip())
File without changes
@@ -0,0 +1,17 @@
1
+ from typing import Any, Dict, List
2
+ from osbot_utils.base_classes.Type_Safe import Type_Safe
3
+ from osbot_utils.helpers.xml.rss.RSS__Image import RSS__Image
4
+ from osbot_utils.helpers.xml.rss.RSS__Item import RSS__Item
5
+
6
+
7
+ class RSS__Channel(Type_Safe):
8
+ description : str
9
+ extensions : Dict[str, Any]
10
+ image : RSS__Image = None
11
+ items : List[RSS__Item]
12
+ language : str
13
+ last_build_date : str
14
+ link : str
15
+ title : str
16
+ update_frequency: str
17
+ update_period : str
@@ -0,0 +1,7 @@
1
+ from osbot_utils.base_classes.Type_Safe import Type_Safe
2
+
3
+
4
+ class RSS__Enclosure(Type_Safe):
5
+ url : str
6
+ type : str
7
+ length : int
@@ -0,0 +1,11 @@
1
+ from typing import Dict, Any
2
+ from osbot_utils.base_classes.Type_Safe import Type_Safe
3
+ from osbot_utils.helpers.xml.rss.RSS__Channel import RSS__Channel
4
+
5
+ DEFAULT__RSS_FEED__VERSION = "2.0"
6
+
7
+ class RSS__Feed(Type_Safe):
8
+ version : str = DEFAULT__RSS_FEED__VERSION
9
+ channel : RSS__Channel = None
10
+ namespaces : Dict[str, str]
11
+ extensions : Dict[str, Any]